# -*- coding: utf-8 -*-
# 请认准 VNPY官方网站 http://www.vnpy.cn
import webbrowser
import psutil as ps
import numpy as np
import pyqtgraph as pg
from PyQt5 import QtWidgets
from PyQt5.QtGui import QPixmap, QIcon
from PyQt5.QtWidgets import QVBoxLayout, QWidget, QDialog, QPushButton, QMessageBox
import time
import os
import shutil
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from PyQt5.QtWidgets import QPushButton
from pyqtgraph import QtCore, QtGui
from PyQt5 import QtWidgets
import configparser
import importlib
import globalvar
import module_backtest
import module_instrumentgroup
import module_talib
import threading
import talib as ta
import pandas as pd
from datetime import datetime


class CandlestickItem(pg.GraphicsObject):
    def __init__(self, data):
        pg.GraphicsObject.__init__(self)
        self.data = data  # data must have fields: time, open, close, min, max
        self.generatepicture()

    def generatepicture(self):
        self.picture = QtGui.QPicture()
        p = QtGui.QPainter(self.picture)
        p.setPen(pg.mkPen('w'))
        # print('输出A：'+str(len(self.data)))
        if len(self.data) == 0:
            pass
        elif len(self.data) == 1:
            if str(self.data) == '[(0, 0, 0, 0, 0, 0, 0)]':
                return
            else:
                w = 0.5
                for (t, tradingday, klinetime, open, close, min, max) in self.data:
                    QApplication.processEvents()
                    p.drawLine(QtCore.QPointF(t, min), QtCore.QPointF(t, max))
                    if open > close:
                        p.setBrush(pg.mkBrush('g'))
                    else:
                        p.setBrush(pg.mkBrush('r'))
                    p.drawRect(QtCore.QRectF(t - w, open, w * 2, close - open))
        else:
            w = (self.data[1][0] - self.data[0][0]) / 3
            for (t, tradingday, klinetime, open, close, min, max) in self.data:
                QApplication.processEvents()
                p.drawLine(QtCore.QPointF(t, min), QtCore.QPointF(t, max))
                if open > close:
                    p.setBrush(pg.mkBrush('g'))
                else:
                    p.setBrush(pg.mkBrush('r'))
                p.drawRect(QtCore.QRectF(t - w, open, w * 2, close - open))
        p.end()

    def paint(self, p, *args):
        p.drawPicture(0, 0, self.picture)

    def boundingRect(self):
        return QtCore.QRectF(self.picture.boundingRect())


class CandlestickItem2(pg.GraphicsObject):
    def __init__(self, data):
        pg.GraphicsObject.__init__(self)
        self.data = data  # fields: time, open, close, min, max
        self.generatepicture()

    def generatepicture(self):
        self.picture = QtGui.QPicture()
        p = QtGui.QPainter(self.picture)
        p.setPen(pg.mkPen('w'))
        # print('输出A：'+str(len(self.data)))
        if len(self.data) == 0:
            pass
        elif len(self.data) == 1:
            if str(self.data) == '[(0, 0, 0, 0, 0, 0, 0)]':
                return
            else:
                w = 0.5
                for (t, tradingday, klinetime, open, close, min, max) in self.data:
                    QApplication.processEvents()
                    p.drawLine(QtCore.QPointF(t, min), QtCore.QPointF(t, max))
                    if open > close:
                        p.setBrush(pg.mkBrush('g'))
                    else:
                        p.setBrush(pg.mkBrush('r'))
                    p.drawRect(QtCore.QRectF(t - w, open, w * 2, close - open))
        else:
            w = (self.data[1][0] - self.data[0][0]) / 3
            for (t, tradingday, klinetime, open, close, min, max) in self.data:
                QApplication.processEvents()
                p.drawLine(QtCore.QPointF(t, min), QtCore.QPointF(t, max))
                if open > close:
                    p.setBrush(pg.mkBrush('g'))
                else:
                    p.setBrush(pg.mkBrush('r'))
                p.drawRect(QtCore.QRectF(t - w, open, w * 2, close - open))
        p.end()

    def paint(self, p, *args):
        p.drawPicture(0, 0, self.picture)

    def boundingRect(self):
        return QtCore.QRectF(self.picture.boundingRect())


class DialogBackTest(QtWidgets.QDialog): pass


class DialogTradeConfirm(QtWidgets.QDialog): pass


class DialogTalib(QtWidgets.QDialog): pass


class DialogStrategyPool(QtWidgets.QDialog): pass


class DialogInvestor(QtWidgets.QDialog): pass


class DialogNewStrategy(QtWidgets.QDialog): pass


class DialogCapitalCurve(QMainWindow): pass


class DialogSetInstrumentID(QtWidgets.QDialog): pass


class DialogSetFilter(QtWidgets.QDialog): pass


class DialogSetStopLossTakeProfit(QtWidgets.QDialog): pass


class DialogSetFilterForKline(QtWidgets.QDialog): pass


class DialogSetParForKline(QtWidgets.QDialog): pass


class DialogEditInstrumentID(QtWidgets.QDialog): pass


class DialogFinishResult(QtWidgets.QDialog): pass


class DialogOpenKline(QtWidgets.QDialog): pass


class DialogOpenKlineForBacktest(QtWidgets.QDialog): pass


class DialogBackTestKline(QtWidgets.QDialog): pass


class DialogParAnalysisReport(QtWidgets.QDialog): pass


class DialogBackTest(QtWidgets.QDialog): pass


# 暂时无用
class DialogTradeConfirm(QtWidgets.QDialog):
    def __init__(self):
        super().__init__()
        self.InitUI()

    def Function_InsertOrder(self):
        pass
        # result = result + globalvar.td.InsertOrder(str(marketdata.contents.InstrumentID, encoding="utf-8"), exchangeid,'1', '0',VN_OPT_LimitPrice , marketdata.contents.LastPrice-10, 1)

    def InitUI(self):
        self.setWindowFlags(Qt.WindowCloseButtonHint)
        self.label_1 = QLabel(self)
        self.label_1.setText("合约")
        self.label_1.move(60, 20)
        self.label_2 = QLabel(self)
        self.label_2.setText("方向")
        self.label_2.move(60, 55)
        self.label_3 = QLabel(self)
        self.label_3.setText("交易密码")
        self.label_3.move(60, 90)
        self.label_7 = QLabel(self)
        self.label_7.setText("输入格式 tcp://ip:port")
        self.label_7.resize(140, 30)
        self.label_7.move(380, 230)
        self.label_8 = QLabel(self)
        self.label_8.setText("APPID")
        self.label_8.move(60, 230)
        self.label_9 = QLabel(self)
        self.label_9.setText("AUTHCODE")
        self.label_9.move(60, 265)
        self.label_10 = QLabel(self)
        self.label_10.setText("ProductInfo")
        self.label_10.move(60, 300)
        self.btn_authcode = QPushButton('如何获取授权码？', self)
        self.btn_authcode.move(330, 265)
        self.btn_authcode.resize(130, 30)
        self.btn_authcode.clicked.connect(self.Function_InsertOrder)
        self.Edit_brokerid = QLineEdit(self)
        self.Edit_brokerid.move(160, 20)
        self.Edit_brokerid.resize(200, 30)
        self.Edit_investor = QLineEdit(self)
        self.Edit_investor.move(160, 55)
        self.Edit_investor.resize(200, 30)
        self.Edit_password = QLineEdit(self)
        self.Edit_password.move(160, 90)
        self.Edit_password.resize(200, 30)
        self.Edit_addr1 = QLineEdit(self)
        self.Edit_addr1.move(160, 125)
        self.Edit_addr1.resize(200, 30)
        self.Edit_addr2 = QLineEdit(self)
        self.Edit_addr2.move(160, 160)
        self.Edit_addr2.resize(200, 30)
        self.Edit_addr3 = QLineEdit(self)
        self.Edit_addr3.move(160, 195)
        self.Edit_addr3.resize(200, 30)
        self.Edit_APPID = QLineEdit(self)
        self.Edit_APPID.move(160, 230)
        self.Edit_APPID.resize(150, 30)
        self.Edit_authcode = QLineEdit(self)
        self.Edit_authcode.move(160, 265)
        self.Edit_authcode.resize(150, 30)
        self.Edit_auserproductinfo = QLineEdit(self)
        self.Edit_auserproductinfo.move(160, 300)
        self.Edit_auserproductinfo.resize(150, 30)
        self.btn_ok = QPushButton('确认修改账户信息2', self)
        self.btn_ok.move(150, 350)
        self.btn_ok.resize(300, 50)
        self.btn_ok.clicked.connect(self.TradeConfirm)
        self.setGeometry(500, 600, 420, 450)
        self.show()
        try:
            global config
            config = configparser.ConfigParser()
            config.read('vnctptd.ini', encoding='utf-8')
            brokeid = config.get('setting', 'brokeid')
            investor = config.get('setting', 'investor')
            password = config.get('setting', 'password')
            appid = config.get('setting', 'appid')
            userproductinfo = config.get('setting', 'userproductinfo')
            authcode = config.get('setting', 'authcode')
            print('read %s %s %s' % (investor, password, appid))
            self.Edit_brokerid.setText(brokeid)
            self.Edit_investor.setText(investor)
            self.Edit_password.setText(password)
            self.Edit_APPID.setText(appid)
            self.Edit_authcode.setText(authcode)
            self.Edit_auserproductinfo.setText(userproductinfo)

        except Exception as e:
            print("initUI Error:" + repr(e))

    def TradeConfirm(self):
        global config
        config = configparser.ConfigParser()
        config.read("vnctptd.ini", encoding="utf-8")  # 读取文件
        config.set("setting", "brokeid", self.Edit_brokerid.text())
        config.set("setting", "investor", self.Edit_investor.text())
        config.set("setting", "password", self.Edit_password.text())
        config.set("setting", "appid", self.Edit_APPID.text())
        config.set("setting", "authcode", self.Edit_authcode.text())
        config.set("setting", "userproductinfo", self.Edit_auserproductinfo.text())
        config.set("setting", "address1", self.Edit_addr1.text())
        config.set("setting", "address2", self.Edit_addr2.text())
        config.set("setting", "address3", self.Edit_addr3.text())
        config.write(open("vnctptd.ini", mode="w"))
        messageBox = QMessageBox()
        messageBox.setWindowTitle('提示')
        messageBox.setText('设置成功,\n需重新启动才可生效，确定关闭VNTrader,人工重启VNTrader吗？')
        messageBox.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
        buttonY = messageBox.button(QMessageBox.Yes)
        buttonY.setText('确定')
        buttonN = messageBox.button(QMessageBox.No)
        buttonN.setText('取消')
        reply = messageBox.exec_()
        if messageBox.clickedButton() == buttonY:
            os._exit(1)
        elif messageBox.clickedButton() == buttonN:
            pass


# Talib指标设置
class DialogTalib(QtWidgets.QDialog):
    class DialogTalibSetting(QtWidgets.QDialog):
        def __init__(self, indicatorsname):
            super().__init__()
            self.indicatorsname = indicatorsname
            self.setWindowIcon(QIcon('ico/talib.ico'))
            self.InitUI()

        def InitUI(self):

            self.setWindowFlags(
                QtCore.Qt.Dialog | QtCore.Qt.WindowStaysOnBottomHint | QtCore.Qt.WindowCloseButtonHint)
            self.tableWidget = QTableWidget()
            self.layout = QHBoxLayout()
            self.tableWidget.setRowCount(5)
            self.tableWidget.setColumnCount(7)
            self.tableWidget.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)  # 所有列自动拉伸，充满界面
            self.tableWidget.setSelectionMode(QAbstractItemView.SingleSelection)  # 设置只能选中一行
            self.tableWidget.setEditTriggers(QTableView.NoEditTriggers)  # 不可编辑
            self.tableWidget.setSelectionBehavior(QAbstractItemView.SelectRows)  # 设置只有行选中
            self.layout.addWidget(self.tableWidget)
            self.setWindowTitle(
                self.indicatorsname + '【' + module_talib.dict_talibparameter[self.indicatorsname][0][1] + '】')

            parnum = int(module_talib.dict_talibparameter[self.indicatorsname][0][0])
            parameter = ['', '', '', '', '', '']
            DEFAULTVALUE = -1
            id = 0
            for k in range(parnum):
                if module_talib.dict_talibparameter[self.indicatorsname][2][k] != DEFAULTVALUE:
                    parameter[id] = module_talib.dict_talibparameter[self.indicatorsname][1][k]
                    id = id + 1

            self.tableWidget.setHorizontalHeaderLabels(
                ['状态', '备注', '参数1', '参数2', '参数3', '参数4', '参数5'])

            self.setLayout(self.layout)
            # 参数个数
            labelpar = []

            for k in range(parnum):
                tempparlabel = QLabel(self)
                tempparlabel.setText(module_talib.dict_talibparameter[self.indicatorsname][1][k])
                tempparlabel.move(60, 220 + k * 40)
                if module_talib.dict_talibparameter[self.indicatorsname][2][k] == DEFAULTVALUE:
                    tempparlabel2 = QLabel(self)
                    tempparlabel2.setText('调用数据')
                    tempparlabel2.move(200, 220 + k * 40)
                else:
                    EditPar = QLineEdit(self)
                    EditPar.setText(str(module_talib.dict_talibparameter[self.indicatorsname][2][k]))
                    EditPar.move(200, 220 + k * 40)
                    EditPar.resize(120, 30)
                labelpar.append(tempparlabel)

            def function_item_clicked(self, QTableWidgetItem):
                check_state = QTableWidgetItem.checkState()
                row = QTableWidgetItem.row()
                if check_state == QtCore.Qt.Checked:
                    if row not in self.delete_row:
                        self.delete_row.append(row)
                elif check_state == QtCore.Qt.Unchecked:
                    if row in self.delete_row:
                        self.delete_row.remove(row)

            if True:
                try:
                    for i in range(len(globalvar.dict_talibcondition[self.indicatorsname])):
                        item = QTableWidgetItem(' 启用该条件')
                        if globalvar.dict_talibcondition[self.indicatorsname][i][1] == 1:
                            item.setCheckState(QtCore.Qt.Checked)
                        else:
                            item.setCheckState(QtCore.Qt.Checked)
                        self.tableWidget.setItem(i, 0, item)
                        item = QTableWidgetItem(globalvar.dict_talibcondition[self.indicatorsname][i][2])
                        self.tableWidget.setItem(i, 1, item)
                        item = QTableWidgetItem(globalvar.dict_talibcondition[self.indicatorsname][i][3])
                        self.tableWidget.setItem(i, 2, item)
                        item = QTableWidgetItem(globalvar.dict_talibcondition[self.indicatorsname][i][4])
                        self.tableWidget.setItem(i, 3, item)
                except Exception as e:
                    print("dict_talibcondition Error:" + repr(e))

            try:
                for i in range(len(module_talib.dict_talibparameter[self.indicatorsname][3][0])):
                    tempparlabel2 = QLabel(self)
                    EditPar = QLineEdit(self)
                    EditPar2 = QLineEdit(self)
                    tempparlabel2.setText(str(module_talib.dict_talibparameter[self.indicatorsname][3][0][0]))
                    tempparlabel2.move(60, 230 + parnum * 40)
                    EditPar.setText('>' + str(module_talib.dict_talibparameter[self.indicatorsname][3][0][1]))
                    EditPar.move(200, 230 + parnum * 40)
                    EditPar.resize(120, 30)
                    EditPar2.setText('趋势条件')
                    EditPar2.move(400, 230 + parnum * 40)
                    EditPar2.resize(120, 30)
            except Exception as e:
                print("talib.csv格式错误 Error:" + repr(e))
                return

            self.btn_ok = QPushButton('添加指标条件', self)
            self.btn_ok.move(300, 480)
            self.btn_ok.resize(300, 50)
            self.btn_ok.clicked.connect(self.SaveCondition)
            Edit2 = QLineEdit(self)
            Edit2.setText('（该指标条件可用于组合成策略）')
            Edit2.move(360, 550)
            Edit2.resize(180, 30)

            self.setGeometry(500, 600, 420, 450)
            self.show()
            try:
                global config
                config = configparser.ConfigParser()
                config.read('vnctptd.ini', encoding='utf-8')
                brokeid = config.get('setting', 'brokeid')
                investor = config.get('setting', 'investor')
                password = config.get('setting', 'password')
                appid = config.get('setting', 'appid')
                userproductinfo = config.get('setting', 'userproductinfo')
                authcode = config.get('setting', 'authcode')
                address1 = config.get('setting', 'address1')
                address2 = config.get('setting', 'address2')
                address3 = config.get('setting', 'address3')
                print('read %s %s %s' % (investor, password, appid))
                self.Edit_brokerid.setText(brokeid)
                self.Edit_investor.setText(investor)
                self.Edit_password.setText(password)
                self.Edit_APPID.setText(appid)
                self.Edit_authcode.setText(authcode)
                self.Edit_auserproductinfo.setText(userproductinfo)
                self.Edit_addr1.setText(address1)
                self.Edit_addr2.setText(address2)
                self.Edit_addr3.setText(address3)
            except Exception as e:
                print("initUI Error:" + repr(e))

        def SaveCondition(self):
            global config
            config = configparser.ConfigParser()
            config.read("vnctptd.ini", encoding="utf-8")  # 读取文件
            config.set("setting", "brokeid", self.Edit_brokerid.text())
            config.set("setting", "investor", self.Edit_investor.text())
            config.set("setting", "password", self.Edit_password.text())
            config.set("setting", "appid", self.Edit_APPID.text())
            config.set("setting", "authcode", self.Edit_authcode.text())
            config.set("setting", "userproductinfo", self.Edit_auserproductinfo.text())
            config.set("setting", "address1", self.Edit_addr1.text())
            config.set("setting", "address2", self.Edit_addr2.text())
            config.set("setting", "address3", self.Edit_addr3.text())
            config.write(open("vnctptd.ini", mode="w"))

            messageBox = QMessageBox()
            messageBox.setWindowTitle('提示')
            messageBox.setText('设置成功,\n需重新启动才可生效，确定关闭VNTrader,人工重启VNTrader吗？')
            messageBox.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
            buttonY = messageBox.button(QMessageBox.Yes)
            buttonY.setText('确定')
            buttonN = messageBox.button(QMessageBox.No)
            buttonN.setText('取消')
            reply = messageBox.exec_()
            strlist = [self.indicatorsname, 0, "", "", ""]
            try:
                if len(globalvar.dict_talibcondition[self.indicatorsname]) == 0:
                    pass
            except Exception as e:
                globalvar.dict_talibcondition[self.indicatorsname] = []
                print("Function_Buttonclicke0 Error:" + repr(e))
            globalvar.dict_talibcondition[self.indicatorsname].append(strlist)

        def showDialog(self):
            text, ok = QInputDialog.getText(self, '选择期货公司自动确认brokeid和ip',
                                            '选择期货公司:')
            if ok:
                self.le.setText(str(text))

    def __init__(self):
        super().__init__()
        self.setWindowIcon(QIcon('ico/talib.ico'))
        self.InitUI()

    def closeEvent(self, event):
        globalvar.DialogTalibState = False
        try:
            if self.dlg_talibindicatrixsetting:
                self.dlg_talibindicatrixsetting.close()
        except Exception as e:
            print("DialogTalib closeEvent Error:" + repr(e))

    def sync_table_double_clicked(self, index):
        column = index.column()
        row = index.row()
        # 取Talib指标名
        strs = self.tableWidget.item(row, column).text()
        print("table: " + strs)
        self.dlg_talibindicatrixsetting = self.DialogTalibSetting(strs)
        self.dlg_talibindicatrixsetting.show()
        self.dlg_talibindicatrixsetting.resize(900, 620)
        # 居中窗口
        screen = QDesktopWidget().screenGeometry()
        size = self.dlg_talibindicatrixsetting.geometry()
        self.dlg_talibindicatrixsetting.move((screen.width() - size.width()) / 2,
                                             (screen.height() - size.height()) / 2)
        self.dlg_talibindicatrixsetting.exec_()

    def InitUI(self):

        self.setWindowFlags(QtCore.Qt.Dialog | QtCore.Qt.WindowStaysOnBottomHint | QtCore.Qt.WindowCloseButtonHint)
        self.tableWidget = QTableWidget()
        self.layout = QHBoxLayout()
        self.tableWidget.setRowCount(200)  # 行数
        self.tableWidget.setColumnCount(5)  # 列数
        self.tableWidget.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
        self.tableWidget.setEditTriggers(QTableView.NoEditTriggers)
        self.layout.addWidget(self.tableWidget)
        self.tableWidget.doubleClicked.connect(self.sync_table_double_clicked)
        self.tableWidget.setHorizontalHeaderLabels(
            ['Talib指标列表', '【TALIB指标正在', '开发集成中，', '请耐心等待】', '', '', ''])
        dict_talibgroup = ta.get_function_groups()
        dict_talibIndicatorstype = {'Cycle Indicators': '周期指标', 'Math Operators': '数学运算符', 'Math Transform': '数学变换',
                                    'Momentum Indicators': '动量指标', 'Overlap Studies': '重叠指标',
                                    'Pattern Recognition': 'K线形态识别', 'Price Transform': '价格指标',
                                    'Statistic Functions': '统计学指标', 'Volatility Indicators': '波动性指标',
                                    'Volume Indicators': '成交量指标'}
        dict_talibIndicatorShow = {'Cycle Indicators': True, 'Math Operators': True, 'Math Transform': True,
                                   'Momentum Indicators': False, 'Overlap Studies': False,
                                   'Pattern Recognition': False, 'Price Transform': True,
                                   'Statistic Functions': True, 'Volatility Indicators': False,
                                   'Volume Indicators': False}

        item = QTableWidgetItem('双击单元格，设置指标自动交易')
        self.tableWidget.setItem(0, 0, item)
        k = 1
        for i, v in enumerate(dict_talibgroup):
            try:
                if dict_talibIndicatorShow[str(v)]:
                    continue
            except Exception as e:
                print("dict_talibIndicatorShow :" + repr(e))
            item = QTableWidgetItem('【' + str(v) + dict_talibIndicatorstype[str(v)] + '】')
            self.tableWidget.setItem(k, 0, item)
            k = k + 1
            for j in range(len(dict_talibgroup[str(v)])):
                # print("  名称：" + dict_talibgroup[str(v)][j])
                item = QTableWidgetItem(dict_talibgroup[str(v)][j])
                self.tableWidget.setItem(k, j, item)
            k = k + len(dict_talibgroup[str(v)]) / 5 + 2
        self.setLayout(self.layout)

    def SaveInvestor(self):
        global config
        config = configparser.ConfigParser()
        config.read("vnctptd.ini", encoding="utf-8")  # 读取文件
        config.set("setting", "brokeid", self.Edit_brokerid.text())
        config.set("setting", "investor", self.Edit_investor.text())
        config.set("setting", "password", self.Edit_password.text())
        config.set("setting", "appid", self.Edit_APPID.text())
        config.set("setting", "authcode", self.Edit_authcode.text())
        config.set("setting", "userproductinfo", self.Edit_auserproductinfo.text())
        config.set("setting", "address1", self.Edit_addr1.text())
        config.set("setting", "address2", self.Edit_addr2.text())
        config.set("setting", "address3", self.Edit_addr3.text())
        config.write(open("vnctptd.ini", mode="w"))
        messageBox = QMessageBox()
        messageBox.setWindowTitle('提示')
        messageBox.setText('设置成功,\n需重新启动才可生效，确定关闭VNTrader,人工重启VNTrader吗？')
        messageBox.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
        buttonY = messageBox.button(QMessageBox.Yes)
        buttonY.setText('确定')
        buttonN = messageBox.button(QMessageBox.No)
        buttonN.setText('取消')
        reply = messageBox.exec_()
        if messageBox.clickedButton() == buttonY:
            os._exit(1)
        elif messageBox.clickedButton() == buttonN:
            pass


# 策略池窗口
class DialogStrategyPool(QtWidgets.QDialog):
    class DialogTalibSetting(QtWidgets.QDialog):
        def __init__(self, indicatorsname):
            super().__init__()
            self.indicatorsname = indicatorsname
            self.setWindowIcon(QIcon('ico/talib.ico'))
            self.InitUI()

        def InitUI(self):
            self.setWindowFlags(
                QtCore.Qt.Dialog | QtCore.Qt.WindowStaysOnBottomHint | QtCore.Qt.WindowCloseButtonHint)
            self.tableWidget = QTableWidget()
            self.layout = QHBoxLayout()
            self.tableWidget.setRowCount(5)
            self.tableWidget.setColumnCount(7)
            self.tableWidget.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
            self.tableWidget.setSelectionMode(QAbstractItemView.SingleSelection)
            self.tableWidget.setEditTriggers(QTableView.NoEditTriggers)
            self.tableWidget.setSelectionBehavior(QAbstractItemView.SelectRows)
            self.layout.addWidget(self.tableWidget)
            self.setWindowTitle(
                self.indicatorsname + '【' + module_talib.dict_talibparameter[self.indicatorsname][0][1] + '】')

            parnum = int(module_talib.dict_talibparameter[self.indicatorsname][0][0])
            parameter = ['', '', '', '', '', '']
            DEFAULTVALUE = -1
            id = 0
            for k in range(parnum):
                if module_talib.dict_talibparameter[self.indicatorsname][2][k] != DEFAULTVALUE:
                    parameter[id] = module_talib.dict_talibparameter[self.indicatorsname][1][k]
                    id = id + 1

            self.tableWidget.setHorizontalHeaderLabels(['状态', '备注', '参数1', '参数2', '参数3', '参数4', '参数5'])

            self.setLayout(self.layout)
            # 参数个数
            labelpar = []

            for k in range(parnum):
                tempparlabel = QLabel(self)
                tempparlabel.setText(module_talib.dict_talibparameter[self.indicatorsname][1][k])
                tempparlabel.move(60, 220 + k * 40)
                if module_talib.dict_talibparameter[self.indicatorsname][2][k] == DEFAULTVALUE:
                    tempparlabel2 = QLabel(self)
                    tempparlabel2.setText('调用数据')
                    tempparlabel2.move(200, 220 + k * 40)
                else:
                    EditPar = QLineEdit(self)
                    EditPar.setText(str(module_talib.dict_talibparameter[self.indicatorsname][2][k]))
                    EditPar.move(200, 220 + k * 40)
                    EditPar.resize(120, 30)
                labelpar.append(tempparlabel)

            def function_item_clicked(self, QTableWidgetItem):
                check_state = QTableWidgetItem.checkState()
                row = QTableWidgetItem.row()
                if check_state == QtCore.Qt.Checked:
                    if row not in self.delete_row:
                        self.delete_row.append(row)
                elif check_state == QtCore.Qt.Unchecked:
                    if row in self.delete_row:
                        self.delete_row.remove(row)

            if True:
                try:
                    for i in range(len(globalvar.dict_talibcondition[self.indicatorsname])):
                        item = QTableWidgetItem(' 启用该条件')
                        if globalvar.dict_talibcondition[self.indicatorsname][i][1] == 1:
                            item.setCheckState(QtCore.Qt.Checked)
                        else:
                            item.setCheckState(QtCore.Qt.Checked)
                        self.tableWidget.setItem(i, 0, item)
                        item = QTableWidgetItem(globalvar.dict_talibcondition[self.indicatorsname][i][2])
                        self.tableWidget.setItem(i, 1, item)
                        item = QTableWidgetItem(globalvar.dict_talibcondition[self.indicatorsname][i][3])
                        self.tableWidget.setItem(i, 2, item)
                        item = QTableWidgetItem(globalvar.dict_talibcondition[self.indicatorsname][i][4])
                        self.tableWidget.setItem(i, 3, item)
                except Exception as e:
                    print("dict_talibcondition Error:" + repr(e))

            try:
                for i in range(len(module_talib.dict_talibparameter[self.indicatorsname][3][0])):
                    tempparlabel2 = QLabel(self)
                    EditPar = QLineEdit(self)
                    EditPar2 = QLineEdit(self)
                    tempparlabel2.setText(str(module_talib.dict_talibparameter[self.indicatorsname][3][0][0]))
                    tempparlabel2.move(60, 230 + parnum * 40)
                    EditPar.setText('>' + str(module_talib.dict_talibparameter[self.indicatorsname][3][0][1]))
                    EditPar.move(200, 230 + parnum * 40)
                    EditPar.resize(120, 30)
                    EditPar2.setText('趋势条件')
                    EditPar2.move(400, 230 + parnum * 40)
                    EditPar2.resize(120, 30)
            except Exception as e:
                print("talib.csv格式错误 Error:" + repr(e))
                return

            self.btn_ok = QPushButton('添加指标条件', self)
            self.btn_ok.move(300, 480)
            self.btn_ok.resize(300, 50)
            self.btn_ok.clicked.connect(self.SaveCondition)
            Edit2 = QLineEdit(self)
            Edit2.setText('（该指标条件可用于组合成策略）')
            Edit2.move(360, 550)
            Edit2.resize(180, 30)

            self.setGeometry(500, 600, 420, 450)
            self.show()
            try:
                global config
                config = configparser.ConfigParser()
                config.read('vnctptd.ini', encoding='utf-8')
                brokeid = config.get('setting', 'brokeid')
                investor = config.get('setting', 'investor')
                password = config.get('setting', 'password')
                appid = config.get('setting', 'appid')
                userproductinfo = config.get('setting', 'userproductinfo')
                authcode = config.get('setting', 'authcode')
                address1 = config.get('setting', 'address1')
                address2 = config.get('setting', 'address2')
                address3 = config.get('setting', 'address3')
                print('read %s %s %s' % (investor, password, appid))
                self.Edit_brokerid.setText(brokeid)
                self.Edit_investor.setText(investor)
                self.Edit_password.setText(password)
                self.Edit_APPID.setText(appid)
                self.Edit_authcode.setText(authcode)
                self.Edit_auserproductinfo.setText(userproductinfo)
                self.Edit_addr1.setText(address1)
                self.Edit_addr2.setText(address2)
                self.Edit_addr3.setText(address3)
            except Exception as e:
                print("initUI Error:" + repr(e))

        def SaveCondition(self):
            global config
            config = configparser.ConfigParser()
            config.read("vnctptd.ini", encoding="utf-8")  # 读取文件
            config.set("setting", "brokeid", self.Edit_brokerid.text())
            config.set("setting", "investor", self.Edit_investor.text())
            config.set("setting", "password", self.Edit_password.text())
            config.set("setting", "appid", self.Edit_APPID.text())
            config.set("setting", "authcode", self.Edit_authcode.text())
            config.set("setting", "userproductinfo", self.Edit_auserproductinfo.text())
            config.set("setting", "address1", self.Edit_addr1.text())
            config.set("setting", "address2", self.Edit_addr2.text())
            config.set("setting", "address3", self.Edit_addr3.text())
            config.write(open("vnctptd.ini", mode="w"))
            messageBox = QMessageBox()
            messageBox.setWindowTitle('提示')
            messageBox.setText('设置成功,\n需重新启动才可生效，确定关闭VNTrader,人工重启VNTrader吗？')
            messageBox.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
            buttonY = messageBox.button(QMessageBox.Yes)
            buttonY.setText('确定')
            buttonN = messageBox.button(QMessageBox.No)
            buttonN.setText('取消')
            reply = messageBox.exec_()
            strlist = [self.indicatorsname, 0, "", "", ""]
            try:
                if len(globalvar.dict_talibcondition[self.indicatorsname]) == 0:
                    pass
            except Exception as e:
                globalvar.dict_talibcondition[self.indicatorsname] = []
                print("Function_Buttonclicke0 Error:" + repr(e))
            globalvar.dict_talibcondition[self.indicatorsname].append(strlist)

        def showDialog(self):
            text, ok = QInputDialog.getText(self, '选择期货公司自动确认brokeid和ip',
                                            '选择期货公司:')
            if ok:
                self.le.setText(str(text))

    def __init__(self):
        super().__init__()
        self.setWindowIcon(QIcon('ico/talib.ico'))
        self.InitUI()

    def closeEvent(self, event):
        globalvar.DialogTalibState = False
        try:
            if self.dlg_talibindicatrixsetting:
                self.dlg_talibindicatrixsetting.close()
        except Exception as e:
            print("DialogTalib closeEvent Error:" + repr(e))

    def sync_table_double_clicked(self, index):
        column = index.column()
        row = index.row()
        # 取Talib指标名
        strs = self.tableWidget.item(row, column).text()
        print("table: " + strs)
        self.dlg_talibindicatrixsetting = self.DialogTalibSetting(strs)
        self.dlg_talibindicatrixsetting.show()
        self.dlg_talibindicatrixsetting.resize(900, 620)
        # 居中窗口
        screen = QDesktopWidget().screenGeometry()
        size = self.dlg_talibindicatrixsetting.geometry()
        self.dlg_talibindicatrixsetting.move((screen.width() - size.width()) / 2,
                                             (screen.height() - size.height()) / 2)
        self.dlg_talibindicatrixsetting.exec_()

    def InitUI(self):

        self.setWindowFlags(QtCore.Qt.Dialog | QtCore.Qt.WindowStaysOnBottomHint | QtCore.Qt.WindowCloseButtonHint)
        self.tableWidget = QTableWidget()
        self.layout = QHBoxLayout()
        self.tableWidget.setRowCount(200)  # 行数
        self.tableWidget.setColumnCount(5)  # 列数
        self.tableWidget.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)  # 所有列自动拉伸，充满界面
        self.tableWidget.setEditTriggers(QTableView.NoEditTriggers)  # 不可编辑
        self.layout.addWidget(self.tableWidget)
        self.tableWidget.doubleClicked.connect(self.sync_table_double_clicked)

        self.tableWidget.setHorizontalHeaderLabels(
            ['Talib指标列表', '【TALIB指标正在', '开发集成中，', '请耐心等待】', '', '', ''])
        dict_talibgroup = ta.get_function_groups()
        dict_talibIndicatorstype = {'Cycle Indicators': '周期指标', 'Math Operators': '数学运算符', 'Math Transform': '数学变换',
                                    'Momentum Indicators': '动量指标', 'Overlap Studies': '重叠指标',
                                    'Pattern Recognition': 'K线形态识别', 'Price Transform': '价格指标',
                                    'Statistic Functions': '统计学指标', 'Volatility Indicators': '波动性指标',
                                    'Volume Indicators': '成交量指标'}
        dict_talibIndicatorShow = {'Cycle Indicators': True, 'Math Operators': True, 'Math Transform': True,
                                   'Momentum Indicators': False, 'Overlap Studies': False,
                                   'Pattern Recognition': False, 'Price Transform': True,
                                   'Statistic Functions': True, 'Volatility Indicators': False,
                                   'Volume Indicators': False}

        item = QTableWidgetItem('双击单元格，设置指标自动交易')
        self.tableWidget.setItem(0, 0, item)

        k = 1
        for i, v in enumerate(dict_talibgroup):
            try:
                if dict_talibIndicatorShow[str(v)]:
                    continue
            except Exception as e:
                print("dict_talibIndicatorShow :" + repr(e))

            item = QTableWidgetItem('【' + str(v) + dict_talibIndicatorstype[str(v)] + '】')
            self.tableWidget.setItem(k, 0, item)
            k = k + 1
            for j in range(len(dict_talibgroup[str(v)])):
                # print("  名称：" + dict_talibgroup[str(v)][j])
                item = QTableWidgetItem(dict_talibgroup[str(v)][j])
                self.tableWidget.setItem(k, j, item)
            k = k + len(dict_talibgroup[str(v)]) / 5 + 2
        self.setLayout(self.layout)

    def SaveInvestor(self):
        global config
        config = configparser.ConfigParser()
        config.read("vnctptd.ini", encoding="utf-8")  # 读取文件
        config.set("setting", "brokeid", self.Edit_brokerid.text())
        config.set("setting", "investor", self.Edit_investor.text())
        config.set("setting", "password", self.Edit_password.text())
        config.set("setting", "appid", self.Edit_APPID.text())
        config.set("setting", "authcode", self.Edit_authcode.text())
        config.set("setting", "userproductinfo", self.Edit_auserproductinfo.text())
        config.set("setting", "address1", self.Edit_addr1.text())
        config.set("setting", "address2", self.Edit_addr2.text())
        config.set("setting", "address3", self.Edit_addr3.text())
        config.write(open("vnctptd.ini", mode="w"))
        messageBox = QMessageBox()
        messageBox.setWindowTitle('提示')
        messageBox.setText('设置成功,\n需重新启动才可生效，确定关闭VNTrader,人工重启VNTrader吗？')
        messageBox.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
        buttonY = messageBox.button(QMessageBox.Yes)
        buttonY.setText('确定')
        buttonN = messageBox.button(QMessageBox.No)
        buttonN.setText('取消')
        reply = messageBox.exec_()
        if messageBox.clickedButton() == buttonY:
            os._exit(1)
        elif messageBox.clickedButton() == buttonN:
            pass

    def showDialog(self):
        text, ok = QInputDialog.getText(self, '选择期货公司自动确认brokeid和ip',
                                        '选择期货公司:')
        if ok:
            self.le.setText(str(text))


# 修改投资者账号
class DialogInvestor(QtWidgets.QDialog):
    def __init__(self):
        super().__init__()
        self.setWindowIcon(QIcon('ico/ico_user.ico'))
        self.InitUI()

    def closeEvent(self, event):
        """
           重写closeEvent方法，实现dialog窗体关闭时执行一些代码
           """
        messagebox = QMessageBox()
        messagebox.setWindowTitle('提示')
        messagebox.setText('是否关闭窗口？')
        messagebox.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
        buttonY = messagebox.button(QMessageBox.Yes)
        buttonY.setText('确定')
        buttonN = messagebox.button(QMessageBox.No)
        buttonN.setText('取消')
        reply = messagebox.exec_()
        if messagebox.clickedButton() == buttonY:
            event.accept()
        elif messagebox.clickedButton() == buttonN:
            event.ignore()

    def Function_OpenUrl_HOWTOGETAUTHCODE(self):
        webbrowser.open('http://www.vnpy.cn/')

    def InitUI(self):
        self.setWindowFlags(Qt.WindowCloseButtonHint)
        self.label_1 = QLabel(self)
        self.label_1.setText("期货公司编码")
        self.label_1.move(60, 20)
        self.label_2 = QLabel(self)
        self.label_2.setText("交易账户")
        self.label_2.move(60, 55)
        self.label_3 = QLabel(self)
        self.label_3.setText("交易密码")
        self.label_3.move(60, 90)
        self.label_4 = QLabel(self)
        self.label_4.setText("交易服务器1")
        self.label_4.move(60, 125)
        self.label_5 = QLabel(self)
        self.label_5.setText("交易服务器2")
        self.label_5.move(60, 160)
        self.label_6 = QLabel(self)
        self.label_6.setText("交易服务器3")
        self.label_6.move(60, 195)
        self.label_7 = QLabel(self)
        self.label_7.setText("输入格式 tcp://ip:port")
        self.label_7.resize(140, 30)
        self.label_7.move(380, 230)
        self.label_8 = QLabel(self)
        self.label_8.setText("APPID")
        self.label_8.move(60, 230)
        self.label_9 = QLabel(self)
        self.label_9.setText("AUTHCODE")
        self.label_9.move(60, 265)
        self.label_10 = QLabel(self)
        self.label_10.setText("ProductInfo")
        self.label_10.move(60, 300)
        self.btn_authcode = QPushButton('如何获取授权码？', self)
        self.btn_authcode.move(330, 265)
        self.btn_authcode.resize(130, 30)
        self.btn_authcode.clicked.connect(self.Function_OpenUrl_HOWTOGETAUTHCODE)
        self.Edit_brokerid = QLineEdit(self)
        self.Edit_brokerid.move(160, 20)
        self.Edit_brokerid.resize(200, 30)
        self.Edit_investor = QLineEdit(self)
        self.Edit_investor.move(160, 55)
        self.Edit_investor.resize(200, 30)
        self.Edit_password = QLineEdit(self)
        self.Edit_password.move(160, 90)
        self.Edit_password.resize(200, 30)
        self.Edit_addr1 = QLineEdit(self)
        self.Edit_addr1.move(160, 125)
        self.Edit_addr1.resize(200, 30)
        self.Edit_addr2 = QLineEdit(self)
        self.Edit_addr2.move(160, 160)
        self.Edit_addr2.resize(200, 30)
        self.Edit_addr3 = QLineEdit(self)
        self.Edit_addr3.move(160, 195)
        self.Edit_addr3.resize(200, 30)
        self.Edit_APPID = QLineEdit(self)
        self.Edit_APPID.move(160, 230)
        self.Edit_APPID.resize(150, 30)
        self.Edit_authcode = QLineEdit(self)
        self.Edit_authcode.move(160, 265)
        self.Edit_authcode.resize(150, 30)
        self.Edit_auserproductinfo = QLineEdit(self)
        self.Edit_auserproductinfo.move(160, 300)
        self.Edit_auserproductinfo.resize(150, 30)
        self.btn_ok = QPushButton('确认修改账户信息', self)
        self.btn_ok.move(150, 350)
        self.btn_ok.resize(300, 50)
        self.btn_ok.clicked.connect(self.SaveInvestor)
        self.setGeometry(500, 600, 420, 450)
        self.show()
        try:
            global config
            config = configparser.ConfigParser()
            # -read读取ini文件
            config.read('vnctptd.ini', encoding='utf-8')
            brokeid = config.get('setting', 'brokeid')
            investor = config.get('setting', 'investor')
            password = config.get('setting', 'password')
            appid = config.get('setting', 'appid')
            userproductinfo = config.get('setting', 'userproductinfo')
            authcode = config.get('setting', 'authcode')
            address1 = config.get('setting', 'address1')
            address2 = config.get('setting', 'address2')
            address3 = config.get('setting', 'address3')
            print('read %s %s %s' % (investor, password, appid))
            self.Edit_brokerid.setText(brokeid)
            self.Edit_investor.setText(investor)
            self.Edit_password.setText(password)
            self.Edit_APPID.setText(appid)
            self.Edit_authcode.setText(authcode)
            self.Edit_auserproductinfo.setText(userproductinfo)
            self.Edit_addr1.setText(address1)
            self.Edit_addr2.setText(address2)
            self.Edit_addr3.setText(address3)
        except Exception as e:
            print("initUI Error:" + repr(e))

    def SaveInvestor(self):
        global config
        config = configparser.ConfigParser()
        config.read("vnctptd.ini", encoding="utf-8")  # 读取文件
        config.set("setting", "brokeid", self.Edit_brokerid.text())
        config.set("setting", "investor", self.Edit_investor.text())
        config.set("setting", "password", self.Edit_password.text())
        config.set("setting", "appid", self.Edit_APPID.text())
        config.set("setting", "authcode", self.Edit_authcode.text())
        config.set("setting", "userproductinfo", self.Edit_auserproductinfo.text())
        config.set("setting", "address1", self.Edit_addr1.text())
        config.set("setting", "address2", self.Edit_addr2.text())
        config.set("setting", "address3", self.Edit_addr3.text())
        config.write(open("vnctptd.ini", mode="w"))
        messageBox = QMessageBox()
        messageBox.setWindowTitle('提示')
        messageBox.setText('设置成功,\n需重新启动才可生效，确定关闭VNTrader,人工重启VNTrader吗？')
        messageBox.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
        buttonY = messageBox.button(QMessageBox.Yes)
        buttonY.setText('确定')
        buttonN = messageBox.button(QMessageBox.No)
        buttonN.setText('取消')
        reply = messageBox.exec_()
        if messageBox.clickedButton() == buttonY:
            os._exit(1)
        elif messageBox.clickedButton() == buttonN:
            pass

    def showDialog(self):
        text, ok = QInputDialog.getText(self, '选择期货公司自动确认brokeid和ip', '选择期货公司:')
        if ok:
            self.le.setText(str(text))


# 新策略
class DialogNewStrategy(QtWidgets.QDialog):
    class DialogNewStrategyStep2(QtWidgets.QDialog):
        def __init__(self, type):
            super().__init__()
            self.type = type
            self.InitUI()

        def InitUI(self):
            self.setWindowFlags(Qt.WindowCloseButtonHint)
            self.label_1 = QLabel(self)
            if self.type == 1:
                self.label_1.setText("策略命名：")
                self.btn_ok = QPushButton('确认添加策略', self)
                self.btn_ok.move(60, 200)
                self.btn_ok.resize(300, 50)
                self.btn_ok.clicked.connect(self.OnNewStrategyStep3)
            else:
                self.label_1.setText("策略过滤规则：")
                self.btn_ok = QPushButton('确认添加策略过滤规则', self)
                self.btn_ok.move(60, 200)
                self.btn_ok.resize(300, 50)
                self.btn_ok.clicked.connect(self.OnNewStrategyFilterStep3)
            self.label_1.move(60, 100)
            self.Edit_Strategy = QLineEdit(self)
            self.Edit_Strategy.move(140, 90)
            self.Edit_Strategy.resize(200, 30)
            self.show()

        def OnNewStrategyStep3(self):
            source1 = globalvar.currpath + '/template/newstrategyfile.ini'
            target1 = globalvar.currpath + '/strategyfile/' + self.Edit_Strategy.text() + '.ini'
            source2 = globalvar.currpath + '/template/newstrategyfile.py'
            target2 = globalvar.currpath + '/strategyfile/' + self.Edit_Strategy.text() + '.py'
            try:
                shutil.copy(source1, target1)
                shutil.copy(source2, target2)
                globalvar.ui.Function_ScanStrategy()
                self.close()
            except IOError as e:
                print("OnNewStrategyStep3 Error:Unable to copy file. %s" % e)

        def OnNewStrategyFilterStep3(self):
            source = globalvar.currpath + '/template/newstrategyfilterfile.py'
            target = globalvar.currpath + '/strategyfile/' + self.Edit_Strategy.text() + '.py'
            try:
                shutil.copy(source, target)
                globalvar.ui.Function_ScanStrategy()
                self.close()
            except IOError as e:
                print("OnNewStrategyFilterStep3 Error:Unable to copy file. %s" % e)

    class DialogNewTalibStrategyStep2(QtWidgets.QDialog):
        class DialogTalibSetting(QtWidgets.QDialog):
            def __init__(self, indicatorsname):
                super().__init__()
                self.indicatorsname = indicatorsname
                self.setWindowIcon(QIcon('ico/talib.ico'))
                self.InitUI()

            def InitUI(self):

                self.setWindowFlags(
                    QtCore.Qt.Dialog | QtCore.Qt.WindowStaysOnBottomHint | QtCore.Qt.WindowCloseButtonHint)
                self.tableWidget = QTableWidget()
                self.layout = QHBoxLayout()
                self.tableWidget.setRowCount(0)  # 行数
                self.tableWidget.setColumnCount(4)  # 列数
                self.tableWidget.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)  # 所有列自动拉伸，充满界面
                self.tableWidget.setSelectionMode(QAbstractItemView.SingleSelection)  # 设置只能选中一行
                self.tableWidget.setEditTriggers(QTableView.NoEditTriggers)  # 不可编辑
                self.tableWidget.setSelectionBehavior(QAbstractItemView.SelectRows);  # 设置只有行选中
                self.layout.addWidget(self.tableWidget)
                self.setWindowTitle(
                    self.indicatorsname + '【' + module_talib.dict_talibparameter[self.indicatorsname][0][1] + '】')

                parnum = int(module_talib.dict_talibparameter[self.indicatorsname][0][0])
                parameter = ['', '', '', '', '', '']
                DEFAULTVALUE = -1
                id = 0
                for k in range(parnum):
                    if module_talib.dict_talibparameter[self.indicatorsname][2][k] != DEFAULTVALUE:
                        parameter[id] = module_talib.dict_talibparameter[self.indicatorsname][1][k]
                        id = id + 1

                self.tableWidget.setHorizontalHeaderLabels(['参数名', '默认参数', '开始', '结束'])
                self.setLayout(self.layout)
                # 参数个数
                labelpar = []

                for k in range(parnum):
                    tempparlabel = QLabel(self)
                    tempparlabel.setText(module_talib.dict_talibparameter[self.indicatorsname][1][k])
                    tempparlabel.move(60, 220 + k * 40)
                    if module_talib.dict_talibparameter[self.indicatorsname][2][k] == DEFAULTVALUE:
                        tempparlabel2 = QLabel(self)
                        tempparlabel2.setText('调用数据')
                        tempparlabel2.move(200, 220 + k * 40)
                    else:
                        EditPar = QLineEdit(self)
                        EditPar.setText(str(module_talib.dict_talibparameter[self.indicatorsname][2][k]))
                        EditPar.move(200, 220 + k * 40)
                        EditPar.resize(120, 30)
                    labelpar.append(tempparlabel)

                def function_item_clicked(self, QTableWidgetItem):
                    check_state = QTableWidgetItem.checkState()
                    row = QTableWidgetItem.row()
                    if check_state == QtCore.Qt.Checked:
                        if row not in self.delete_row:
                            self.delete_row.append(row)
                    elif check_state == QtCore.Qt.Unchecked:
                        if row in self.delete_row:
                            self.delete_row.remove(row)

                if True:
                    try:
                        for i in range(len(globalvar.dict_talibcondition[self.indicatorsname])):
                            # print('lid: ' + str(globalvar.dict_talibcondition[self.indicatorsname][i]))
                            item = QTableWidgetItem(' 启用该条件')
                            if globalvar.dict_talibcondition[self.indicatorsname][i][1] == 1:
                                item.setCheckState(QtCore.Qt.Checked)
                            else:
                                item.setCheckState(QtCore.Qt.Checked)
                            self.tableWidget.setItem(i, 0, item)
                            item = QTableWidgetItem(globalvar.dict_talibcondition[self.indicatorsname][i][2])
                            self.tableWidget.setItem(i, 1, item)
                            item = QTableWidgetItem(globalvar.dict_talibcondition[self.indicatorsname][i][3])
                            self.tableWidget.setItem(i, 2, item)
                            item = QTableWidgetItem(globalvar.dict_talibcondition[self.indicatorsname][i][4])
                            self.tableWidget.setItem(i, 3, item)
                    except Exception as e:
                        print("dict_talibcondition Error:" + repr(e))

                try:
                    for i in range(len(module_talib.dict_talibparameter[self.indicatorsname][3][0])):
                        tempparlabel2 = QLabel(self)
                        EditPar = QLineEdit(self)
                        EditPar2 = QLineEdit(self)
                        tempparlabel2.setText(str(module_talib.dict_talibparameter[self.indicatorsname][3][0][0]))
                        tempparlabel2.move(60, 230 + parnum * 40)
                        EditPar.setText('>' + str(module_talib.dict_talibparameter[self.indicatorsname][3][0][1]))
                        EditPar.move(200, 230 + parnum * 40)
                        EditPar.resize(120, 30)
                        EditPar2.setText('策略名称')
                        EditPar2.move(400, 230 + parnum * 40)
                        EditPar2.resize(120, 30)
                except Exception as e:
                    print("talib.csv格式错误 Error:" + repr(e))
                    return

                self.btn_ok = QPushButton('添加该策略模板', self)
                self.btn_ok.move(300, 480)
                self.btn_ok.resize(300, 50)
                self.btn_ok.clicked.connect(self.SaveCondition)
                Edit2 = QLineEdit(self)
                Edit2.setText('（该指标条件可用于组合成策略）')
                Edit2.move(360, 550)
                Edit2.resize(180, 30)

                self.setGeometry(500, 600, 420, 450)
                self.show()
                try:
                    global config
                    config = configparser.ConfigParser()
                    config.read('vnctptd.ini', encoding='utf-8')
                    brokeid = config.get('setting', 'brokeid')
                    investor = config.get('setting', 'investor')
                    password = config.get('setting', 'password')
                    appid = config.get('setting', 'appid')
                    userproductinfo = config.get('setting', 'userproductinfo')
                    authcode = config.get('setting', 'authcode')
                    address1 = config.get('setting', 'address1')
                    address2 = config.get('setting', 'address2')
                    address3 = config.get('setting', 'address3')
                    print('read %s %s %s' % (investor, password, appid))
                    self.Edit_brokerid.setText(brokeid)
                    self.Edit_investor.setText(investor)
                    self.Edit_password.setText(password)
                    self.Edit_APPID.setText(appid)
                    self.Edit_authcode.setText(authcode)
                    self.Edit_auserproductinfo.setText(userproductinfo)
                    self.Edit_addr1.setText(address1)
                    self.Edit_addr2.setText(address2)
                    self.Edit_addr3.setText(address3)
                except Exception as e:
                    print("initUI Error:" + repr(e))

            def SaveCondition(self):
                global config
                config = configparser.ConfigParser()
                config.read("vnctptd.ini", encoding="utf-8")  # 读取文件
                config.set("setting", "brokeid", self.Edit_brokerid.text())
                config.set("setting", "investor", self.Edit_investor.text())
                config.set("setting", "password", self.Edit_password.text())
                config.set("setting", "appid", self.Edit_APPID.text())
                config.set("setting", "authcode", self.Edit_authcode.text())
                config.set("setting", "userproductinfo", self.Edit_auserproductinfo.text())
                config.set("setting", "address1", self.Edit_addr1.text())
                config.set("setting", "address2", self.Edit_addr2.text())
                config.set("setting", "address3", self.Edit_addr3.text())
                config.write(open("vnctptd.ini", mode="w"))
                messageBox = QMessageBox()
                messageBox.setWindowTitle('提示')
                messageBox.setText('设置成功,\n需重新启动才可生效，确定关闭VNTrader,人工重启VNTrader吗？')
                messageBox.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
                buttonY = messageBox.button(QMessageBox.Yes)
                buttonY.setText('确定')
                buttonN = messageBox.button(QMessageBox.No)
                buttonN.setText('取消')
                reply = messageBox.exec_()

                strlist = [self.indicatorsname, 0, "", "", ""]
                try:
                    if len(globalvar.dict_talibcondition[self.indicatorsname]) == 0:
                        pass
                except Exception as e:
                    globalvar.dict_talibcondition[self.indicatorsname] = []
                    print("Function_Buttonclicke0 Error:" + repr(e))
                globalvar.dict_talibcondition[self.indicatorsname].append(strlist)

            def showDialog(self):
                text, ok = QInputDialog.getText(self, '选择期货公司自动确认brokeid和ip',
                                                '选择期货公司:')
                if ok:
                    self.le.setText(str(text))

        def __init__(self):
            super().__init__()
            self.setWindowIcon(QIcon('ico/talib.ico'))
            self.InitUI()

        def closeEvent(self, event):
            globalvar.DialogTalibState = False
            try:
                if self.dlg_talibindicatrixsetting:
                    self.dlg_talibindicatrixsetting.close()
            except Exception as e:
                print("DialogTalib closeEvent Error:" + repr(e))

        def sync_table_double_clicked(self, index):
            column = index.column()
            row = index.row()
            # 取Talib指标名
            strs = self.tableWidget.item(row, column).text()
            print("table: " + strs)
            self.dlg_talibindicatrixsetting = self.DialogTalibSetting(strs)
            self.dlg_talibindicatrixsetting.show()
            self.dlg_talibindicatrixsetting.resize(900, 620)
            # 居中窗口
            screen = QDesktopWidget().screenGeometry()
            size = self.dlg_talibindicatrixsetting.geometry()
            self.dlg_talibindicatrixsetting.move((screen.width() - size.width()) / 2,
                                                 (screen.height() - size.height()) / 2)
            self.dlg_talibindicatrixsetting.exec_()

        def InitUI(self):

            self.setWindowFlags(
                QtCore.Qt.Dialog | QtCore.Qt.WindowStaysOnBottomHint | QtCore.Qt.WindowCloseButtonHint)
            self.tableWidget = QTableWidget()
            self.layout = QHBoxLayout()
            self.tableWidget.setRowCount(200)  # 行数
            self.tableWidget.setColumnCount(5)  # 列数
            self.tableWidget.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)  # 所有列自动拉伸，充满界面
            # tableWidget.setSelectionMode(QAbstractItemView.SingleSelection)  # 设置只能选中一行
            self.tableWidget.setEditTriggers(QTableView.NoEditTriggers)  # 不可编辑
            # tableWidget.setSelectionBehavior(QAbstractItemView.SelectRows);  # 设置只有行选中
            self.layout.addWidget(self.tableWidget)
            # self.connect(tableWidget,  itemClicked, this, & DialogTalib::enter);

            self.tableWidget.doubleClicked.connect(self.sync_table_double_clicked)

            self.tableWidget.setHorizontalHeaderLabels(
                ['Talib指标列表', '【TALIB指标正在', '开发集成中，', '请耐心等待】', '', '',
                 ''])  # 横向标题排列，如果使用setVerticalHeaderLabels则是纵向排列标题

            # 输出Talib支持所有的函数
            '''
               li = ta.get_functions()
               for i in range(len(li)):
                   item = QTableWidgetItem(str(li[i]))
                   self.tableWidget.setItem(0, i, item)

               '''
            dict_talibgroup = ta.get_function_groups()

            dict_talibIndicatorstype = {'Cycle Indicators': '周期指标', 'Math Operators': '数学运算符',
                                        'Math Transform': '数学变换',
                                        'Momentum Indicators': '动量指标', 'Overlap Studies': '重叠指标',
                                        'Pattern Recognition': 'K线形态识别', 'Price Transform': '价格指标',
                                        'Statistic Functions': '统计学指标', 'Volatility Indicators': '波动性指标',
                                        'Volume Indicators': '成交量指标'}
            dict_talibIndicatorShow = {'Cycle Indicators': True, 'Math Operators': True, 'Math Transform': True,
                                       'Momentum Indicators': False, 'Overlap Studies': False,
                                       'Pattern Recognition': False, 'Price Transform': True,
                                       'Statistic Functions': True, 'Volatility Indicators': False,
                                       'Volume Indicators': False}

            item = QTableWidgetItem('双击单元格，设置指标自动交易')
            self.tableWidget.setItem(0, 0, item)

            k = 1
            for i, v in enumerate(dict_talibgroup):
                try:
                    if dict_talibIndicatorShow[str(v)]:
                        continue
                except Exception as e:
                    print("dict_talibIndicatorShow :" + repr(e))

                item = QTableWidgetItem('【' + str(v) + dict_talibIndicatorstype[str(v)] + '】')
                self.tableWidget.setItem(k, 0, item)
                k = k + 1
                for j in range(len(dict_talibgroup[str(v)])):
                    # print("  名称：" + dict_talibgroup[str(v)][j])
                    item = QTableWidgetItem(dict_talibgroup[str(v)][j])
                    self.tableWidget.setItem(k, j, item)
                k = k + len(dict_talibgroup[str(v)]) / 5 + 2

            # 输出Talib支持所有的函数
            # li2 = ta.get_function_groups()
            # for j in range(len(li2)):
            #    print(str(li2[j]))
            # print ('get_function_groups'+ str(ta.get_function_groups()))

            self.setLayout(self.layout)

        def SaveInvestor(self):
            global config
            config = configparser.ConfigParser()
            config.read("vnctptd.ini", encoding="utf-8")  # 读取文件
            config.set("setting", "brokeid", self.Edit_brokerid.text())
            config.set("setting", "investor", self.Edit_investor.text())
            config.set("setting", "password", self.Edit_password.text())
            config.set("setting", "appid", self.Edit_APPID.text())
            config.set("setting", "authcode", self.Edit_authcode.text())
            config.set("setting", "userproductinfo", self.Edit_auserproductinfo.text())
            config.set("setting", "address1", self.Edit_addr1.text())
            config.set("setting", "address2", self.Edit_addr2.text())
            config.set("setting", "address3", self.Edit_addr3.text())
            config.write(open("vnctptd.ini", mode="w"))
            messageBox = QMessageBox()
            messageBox.setWindowTitle('提示')
            messageBox.setText('设置成功,\n需重新启动才可生效，确定关闭VNTrader,人工重启VNTrader吗？')
            messageBox.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
            buttonY = messageBox.button(QMessageBox.Yes)
            buttonY.setText('确定')
            buttonN = messageBox.button(QMessageBox.No)
            buttonN.setText('取消')
            reply = messageBox.exec_()
            if messageBox.clickedButton() == buttonY:
                os._exit(1)
            elif messageBox.clickedButton() == buttonN:
                pass

        def showDialog(self):
            text, ok = QInputDialog.getText(self, '选择期货公司自动确认brokeid和ip',
                                            '选择期货公司:')
            if ok:
                self.le.setText(str(text))

    def __init__(self, type):
        super().__init__()
        self.type = type
        self.setWindowIcon(QIcon('ico/ico_new.png'))
        self.InitUI()

    def InitUI(self):

        self.btn1 = QtWidgets.QPushButton()
        self.btn1.clicked.connect(self.OnNewStrategy)
        self.btn1.setObjectName("btn1")
        self.btn1.setSizePolicy(QtGui.QSizePolicy.Fixed, 0)
        if self.type == 1:
            self.btn1.setStyleSheet("QPushButton{border-image: url(ico/ico_newstrategy.png)}")
        else:
            self.btn1.setStyleSheet("QPushButton{border-image: url(ico/ico_newstrategyfilter.png)}")
        self.btn1.setFixedSize(248, 60)
        self.vbox = QVBoxLayout()
        self.vbox.setAlignment(Qt.AlignCenter)
        self.vbox.addWidget(self.btn1)
        self.setLayout(self.vbox)
        self.setWindowFlags(Qt.WindowCloseButtonHint)
        self.show()

    # 由模板创建策略文件
    def OnNewStrategy(self):
        ui_demo = self.DialogNewStrategyStep2(self.type)
        ui_demo.setWindowFlags(
            QtCore.Qt.Dialog | QtCore.Qt.WindowStaysOnBottomHint | QtCore.Qt.WindowCloseButtonHint)
        screen = QDesktopWidget().screenGeometry()
        size = ui_demo.geometry()
        newLeft = (screen.width() - size.width()) / 2
        newTop = (screen.height() - size.height()) / 2
        ui_demo.move(newLeft, newTop)
        if self.type == 1:
            ui_demo.setWindowTitle('添加空白策略')
        else:
            ui_demo.setWindowTitle('添加空白策略过滤规则')
        ui_demo.show()
        ui_demo.exec_()
        self.close()

    def NewTalibStrategy(self):
        ui_demo = self.DialogNewTalibStrategyStep2()
        screen = QDesktopWidget().screenGeometry()
        size = ui_demo.geometry()
        ui_demo.move((screen.width() - size.width()) / 2, (screen.height() - size.height()) / 2)
        ui_demo.setWindowTitle('添加Talib策略(正在升级中，目前此窗口功能不完整)')
        ui_demo.resize(800, 600)
        ui_demo.show()
        ui_demo.exec_()
        self.close()


# 资金曲线
class DialogCapitalCurve(QMainWindow):
    def __init__(self):
        super().__init__()
        self.InitUI()

    def Function_OpenUrl_HOWTOGETAUTHCODE(self):
        webbrowser.open('http://www.vnpy.cn/')

    def InitUI(self):
        self.setWindowFlags(QtCore.Qt.Dialog | QtCore.Qt.WindowStaysOnBottomHint | QtCore.Qt.WindowCloseButtonHint)
        self.btn_helper = QPushButton('选择期货公司', self)
        self.btn_helper.move(300, 20)
        self.btn_helper.clicked.connect(self.showDialog)
        self.label_1 = QLabel(self)
        self.label_1.setText("期货公司编码")
        self.label_1.move(60, 20)
        self.label_2 = QLabel(self)
        self.label_2.setText("交易账户")
        self.label_2.move(60, 55)
        self.label_3 = QLabel(self)
        self.label_3.setText("交易密码")
        self.label_3.move(60, 90)
        self.label_4 = QLabel(self)
        self.label_4.setText("交易服务器")
        self.label_4.move(60, 125)
        self.label_4b = QLabel(self)
        self.label_4b.setText("输入格式 tcp://ip:port")
        self.label_4b.resize(140, 30)
        self.label_4b.move(300, 125)
        self.label_5 = QLabel(self)
        self.label_5.setText("APPID")
        self.label_5.move(60, 160)
        self.label_6 = QLabel(self)
        self.label_6.setText("AUTHCODE")
        self.label_6.move(60, 195)
        self.btn_authcode = QPushButton('如何获取授权码？', self)
        self.btn_authcode.move(300, 195)
        self.btn_authcode.resize(130, 30)
        self.btn_authcode.clicked.connect(self.Function_OpenUrl_HOWTOGETAUTHCODE)
        self.Edit_brokerid = QLineEdit(self)
        self.Edit_brokerid.move(140, 20)
        self.Edit_brokerid.resize(150, 30)
        self.Edit_investor = QLineEdit(self)
        self.Edit_investor.move(140, 55)
        self.Edit_investor.resize(150, 30)
        self.Edit_password = QLineEdit(self)
        self.Edit_password.move(140, 90)
        self.Edit_password.resize(150, 30)
        self.Edit_addr = QLineEdit(self)
        self.Edit_addr.move(140, 125)
        self.Edit_addr.resize(150, 30)
        self.Edit_APPID = QLineEdit(self)
        self.Edit_APPID.move(140, 160)
        self.Edit_APPID.resize(150, 30)
        self.Edit_authcode = QLineEdit(self)
        self.Edit_authcode.move(140, 195)
        self.Edit_authcode.resize(150, 30)
        self.btn_ok = QPushButton('确认添加该账户', self)
        self.btn_ok.move(170, 250)
        self.btn_ok.clicked.connect(self.showDialog)
        self.setGeometry(300, 300, 290, 150)
        self.show()

    def showDialog(self):
        text, ok = QInputDialog.getText(self, '选择期货公司自动确认brokeid和ip',
                                        '选择期货公司:')

        if ok:
            self.le.setText(str(text))


# 量化回测窗口
class DialogBackTest(QtWidgets.QDialog):
    def __init__(self, strategyname):
        super().__init__()
        self.strategyname = strategyname
        self.mainstrategyname = os.path.splitext(strategyname)[0]
        self.mainstrategyname = self.mainstrategyname.replace('strategyfile\\', "")
        self.csvstrategyname = os.path.splitext(strategyname)[0] + '.csv'
        print(self.strategyname)
        print('mainstrategyname: ' + self.mainstrategyname)
        print('csvstrategyname: ' + self.csvstrategyname)

        # CPU逻辑核心
        cpunum1 = ps.cpu_count(False)  # 物理CPU
        cpunum2 = ps.cpu_count()  # 逻辑CPU
        self.maxprocessnum = max(int(float(cpunum2 - cpunum1)), 0) + cpunum1
        # 根据参数设置计算处的任务总数
        globalvar.totaltasknum = 0
        globalvar.finishtasknum = 0
        # 回测状态
        globalvar.backteststate = 0
        self.bt = 0
        # 任务进度条列表
        self.progressbarlist = []
        self.dict_processid = {}
        # 是否显示人工选择的资金曲线
        self.selectbacktestcurl = True
        self.finishnum = 0
        self.setWindowIcon(QIcon('ico/ico_doc.ico'))
        self.InitUI()

    def closeEvent(self, event):
        """
           重写closeEvent方法，实现dialog窗体关闭时执行一些代码
           """
        globalvar.DialogSetInstrumentState = False
        messagebox = QMessageBox(None)
        messagebox.setIcon(QMessageBox.Warning)
        messagebox.setText('是否关闭回测窗口？\n关闭窗口后将终止所有回测进程!')
        messagebox.setWindowTitle(('系统提示'))
        messagebox.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
        buttonY = messagebox.button(QMessageBox.Yes)
        buttonY.setText('确定退出')
        buttonN = messagebox.button(QMessageBox.No)
        buttonN.setText('取消')
        # messagebox.setIconPixmap(QPixmap("ico/ico_pool.png"))
        buttonY.setIcon(QtGui.QIcon('ico/ico_yes.png'))
        buttonN.setIcon(QtGui.QIcon('ico/ico_no.png'))
        reply = messagebox.exec_()
        if messagebox.clickedButton() == buttonY:
            # self.OnClosePythonProcess()
            if globalvar.pool != 0:
                globalvar.DialogBackTestPoint.OnCloseProcesswindow()
                globalvar.pool.close()
                # globalvar.pool.terminate()
                globalvar.pool.join()
            self.closestate = True
            event.accept()
        elif messagebox.clickedButton() == buttonN:
            event.ignore()

    '''
       def sync_table_double_clicked(self, index):
           column = index.column()
           row = index.row()
           self.strategyname = self.tableWidget.item(row, column).text()
           print("table1: " + self.name)
       '''

    # 从文件读取合约组信息
    def ReadInstrumentIDGroupInfo(self, filename):
        grouplist = []
        with open(filename, 'r') as f:
            for line in f:
                grouplist = line.strip('\n').split(',')
        return len(grouplist)

    def Log(self, str):
        _translate = QtCore.QCoreApplication.translate
        __sortingEnabled = self.list_backtestlog.isSortingEnabled()
        item = QtWidgets.QListWidgetItem()
        self.list_backtestlog.addItem(item)
        item = self.list_backtestlog.item(self.list_backtestlog.count() - 1)
        item.setText(_translate("MainWindow", str))

    def dynamic_import(self, module):
        return importlib.import_module(module)

    def Function_UpdateEquityCurveForButton(self):
        button = globalvar.ui.MainWindow.sender()
        if button:
            row = self.table_thispargroup.indexAt(button.pos()).row()
            try:
                # 读取资金曲线数据文件，并更新到pyqtgraph
                self.selectbacktestcurl = False
                tempstr = self.table_thispargroup.item(row, 2).text() + '_' + \
                          self.table_thispargroup.item(row, 3).text() + '_' + \
                          self.table_thispargroup.item(row, 4).text() + '_' + \
                          self.table_thispargroup.item(row, 5).text() + '_' + \
                          self.table_thispargroup.item(row, 6).text() + '_' + \
                          self.table_thispargroup.item(row, 7).text() + '.txt'
                filename_curl = self.table_thispargroup.item(row, 0).text() + '/' + tempstr
                filename_tradingrecord = self.table_thispargroup.item(row, 0).text() + '/tradingrecord/' + tempstr
                list_tradingday = self.AddTradingRecordShow(filename_tradingrecord)
                data_backtest = []
                data_index_buy = []
                data_value_buy = []
                data_index_sell = []
                data_value_sell = []
                index = 0
                with open(filename_curl, 'r') as f:
                    for line in f:
                        # QApplication.processEvents()
                        linelist = line.strip('\n').split(',')
                        data_backtest.append(float(linelist[2]))
                        index += 1
                        if len(linelist[1]) == 5:
                            linelist[1] = '0' + linelist[1]
                        for key in list_tradingday[0]:
                            if key == linelist[0] + linelist[1]:
                                data_index_buy.append(index * 1.0)
                                data_value_buy.append(float(linelist[2]) * 1.0)
                        for key in list_tradingday[1]:
                            if key == linelist[0] + linelist[1]:
                                data_index_sell.append(index * 1.0)
                                data_value_sell.append(float(linelist[2]) * 1.0)

                self.curve_realtime.setData(np.hstack(data_backtest))
                # 在最近曲线加信号点
                self.curve_buy.setData(np.hstack(data_index_buy),
                                       np.hstack(data_value_buy))
                self.curve_sell.setData(np.hstack(data_index_sell),
                                        np.hstack(data_value_sell))

            except Exception as e:
                print("Function_UpdateEquityCurveForButton Error:" + repr(e))

    def Function_UpdateEquityCurve(self):
        # 回测窗口，双击记录显示资金曲线
        try:
            # 读取资金曲线数据文件，并更新到pyqtgraph
            self.selectbacktestcurl = False
            tempstr = self.table_thispargroup.selectedItems()[
                          2].text() + '_' + self.table_thispargroup.selectedItems()[3].text() + '_' + \
                      self.table_thispargroup.selectedItems()[
                          4].text() + '_' + self.table_thispargroup.selectedItems()[5].text() + '_' + \
                      self.table_thispargroup.selectedItems()[6].text() + '_' + \
                      self.table_thispargroup.selectedItems()[
                          7].text() + '.txt'
            filename_curl = self.table_thispargroup.selectedItems()[0].text() + '/' + tempstr
            filename_tradingrecord = self.table_thispargroup.selectedItems()[0].text() + '/tradingrecord/' + tempstr
            list_tradingday = self.AddTradingRecordShow(filename_tradingrecord)
            data_backtest = []
            data_index_buy = []
            data_value_buy = []
            data_index_sell = []
            data_value_sell = []
            index = 0
            with open(filename_curl, 'r') as f:
                for line in f:
                    linelist = line.strip('\n').split(',')
                    data_backtest.append(float(linelist[2]))
                    index += 1
                    if len(linelist[1]) == 5:
                        linelist[1] = '0' + linelist[1]
                    for key in list_tradingday[0]:
                        if key == linelist[0] + linelist[1]:
                            data_index_buy.append(index * 1.0)
                            data_value_buy.append(float(linelist[2]) * 1.0)
                    for key in list_tradingday[1]:
                        if key == linelist[0] + linelist[1]:
                            data_index_sell.append(index * 1.0)
                            data_value_sell.append(float(linelist[2]) * 1.0)
            self.curve_realtime.setData(np.hstack(data_backtest))
            # 在最近曲线加信号点
            self.curve_buy.setData(np.hstack(data_index_buy),
                                   np.hstack(data_value_buy))
            self.curve_sell.setData(np.hstack(data_index_sell),
                                    np.hstack(data_value_sell))

            # 更新窗口K线
            globalvar.ui_bt.signal_backtestkline.emit([filename_tradingrecord, filename_curl])

        except Exception as e:
            pass

    def Function_UpdateEquityCurveByFileName(self, filename, list_tradingday):
        # 读取资金曲线数据文件，并更新到pyqtgraph
        try:
            data_backtest = []
            data_index_buy = []
            data_value_buy = []
            data_index_sell = []
            data_value_sell = []
            index = 0
            with open(filename, 'r') as f:
                for line in f:
                    linelist = line.strip('\n').split(',')
                    data_backtest.append(float(linelist[2]))
                    if len(linelist[1]) == 5:
                        linelist[1] = '0' + linelist[1]
                    index += 1
                    if len(linelist[1]) == 5:
                        linelist[1] = '0' + linelist[1]
                    if True:
                        for key in list_tradingday[0]:
                            if key == linelist[0] + linelist[1]:
                                data_index_buy.append(index)
                                data_value_buy.append(float(linelist[2]))
                        for key in list_tradingday[1]:
                            if key == linelist[0] + linelist[1]:
                                data_index_sell.append(index)
                                data_value_sell.append(float(linelist[2]))
            self.wincurl.setWindowTitle('回测资金曲线')
            self.curve_realtime.setData(np.hstack(data_backtest))
            self.curve_buy.setData(np.hstack(data_index_buy),
                                   np.hstack(data_value_buy))
            self.curve_sell.setData(np.hstack(data_index_sell),
                                    np.hstack(data_value_sell))

        except Exception as e:
            pass

    def Function_ReadInstrumentEquityCurve(self):
        print('Function_ReadInstrumentEquityCurve')
        instrumentfilename = self.table_righttop.selectedItems()[0].text()
        print('instrumentfilename: ' + instrumentfilename)
        pathlist = self.table_righttop.selectedItems()[0].text().split('/')
        indexfilename = 'backtestreport/' + self.mainstrategyname + '/' + pathlist[0] + '/resultlist.csv'
        if not os.path.exists(indexfilename):
            print("[%s] File does not exist" % indexfilename)
            return

        indexfilename2 = indexfilename.replace("resultlist.csv", "")
        strlist = indexfilename2.split("/")
        titlepath = strlist[0] + '/' + strlist[1] + '/' + instrumentfilename + '/'
        ui_demo = globalvar.ui.DialogFinishResult(titlepath, indexfilename)
        ui_demo.setWindowTitle('回测结果：' + titlepath)
        screen = QDesktopWidget().screenGeometry()
        size = ui_demo.geometry()
        ui_demo.move((screen.width() - size.width()) / 2,
                     (screen.height() - size.height()) / 2)
        ui_demo.show()
        ui_demo.resize(1024, 600)
        ui_demo.exec_()

    # 删除勾选的记录
    def Function_delete_select(self, QTableWidgetItem):
        check_state = QTableWidgetItem.checkState()
        row = QTableWidgetItem.row()
        if check_state == QtCore.Qt.Checked:
            if row not in self.delete_row:
                self.delete_row.append(row)
        elif check_state == QtCore.Qt.Unchecked:
            if row in self.delete_row:
                self.delete_row.remove(row)

    # 删除按钮行的记录
    def Function_delete_clicked(self, arg):
        button = self.sender()
        if button:
            row = self.table_righttop.indexAt(button.pos()).row()
            self.table_righttop.removeRow(row)

    def Function_ReadInstrumentEquityCurveForButton(self):
        button = self.sender()
        if button:
            row = self.table_righttop.indexAt(button.pos()).row()
        instrumentfilename = self.table_righttop.item(row, 0).text()
        pathlist = instrumentfilename.split('/')
        indexfilename = 'backtestreport/' + self.mainstrategyname + '/' + pathlist[0] + '/resultlist.csv'
        if not os.path.exists(indexfilename):
            print("[%s] File does not exist" % indexfilename)
            return
        indexfilename2 = indexfilename.replace("resultlist.csv", "")
        strlist = indexfilename2.split("/")
        titlepath = strlist[0] + '/' + strlist[1] + '/' + instrumentfilename + '/'
        ui_demo = globalvar.ui.DialogFinishResult(titlepath, indexfilename)
        ui_demo.setWindowTitle('回测结果：' + titlepath)
        screen = QDesktopWidget().screenGeometry()
        size = ui_demo.geometry()
        ui_demo.move((screen.width() - size.width()) / 2,
                     (screen.height() - size.height()) / 2)
        ui_demo.show()
        ui_demo.resize(1024, 600)
        ui_demo.exec_()

    def Function_OpenBackTestKline(self):
        if not os.path.exists(globalvar.csvfile):
            globalvar.csvfile = ''
        screen = QDesktopWidget().screenGeometry()
        globalvar.ui_bt = globalvar.ui.DialogBackTestKline(globalvar.csvfile)
        globalvar.ui_bt.setWindowTitle('双击参数组显示该参数组量化回测数据文件K线图：' + globalvar.csvfile)
        globalvar.ui_bt.resize(max(1000, screen.width() * 0.65), max(748, screen.height() * 0.8))
        globalvar.ui_bt.signal_backtestkline.connect(globalvar.ui_bt.callback_LoadData)
        # 居中窗口
        size = globalvar.ui_bt.geometry()
        globalvar.ui_bt.move((screen.width() - size.width()) / 2 + 200,
                             (screen.height() - size.height()) / 2)
        globalvar.ui_bt.show()

    def GetFilterNum(self):
        config = configparser.ConfigParser()
        config.read(self.strategyname.replace(".py", ".ini"), encoding="utf-8")
        # config.read(self.strategyname.replace(".py", ".ini"))
        filterstr1 = config.get("setting", "openrule1").split(",")[0]
        filterstr2 = config.get("setting", "closerule1").split(",")[0]
        filterstr3 = config.get("setting", "openrule2").split(",")[0]
        filterstr4 = config.get("setting", "closerule2").split(",")[0]
        filterstr5 = config.get("setting", "openrule3").split(",")[0]
        filterstr6 = config.get("setting", "closerule3").split(",")[0]
        filternum = 0
        if filterstr1 != "":
            filternum = filternum + 1
        if filterstr2 != "":
            filternum = filternum + 1
        if filterstr3 != "":
            filternum = filternum + 1
        if filterstr4 != "":
            filternum = filternum + 1
        if filterstr5 != "":
            filternum = filternum + 1
        if filterstr6 != "":
            filternum = filternum + 1
        return filternum

    def InitUI(self):
        target = "temp\\filter.ini"
        self.strategynameini = os.path.splitext(self.strategyname)[0] + '.ini'
        globalvar.ui.ClearPath("temp", ".ini")
        if not os.path.exists(target):
            shutil.copy(self.strategynameini, target)
        self.setWindowFlags(Qt.WindowMinMaxButtonsHint | Qt.WindowCloseButtonHint)
        self.layout = QHBoxLayout()
        self.table_lefttop = QtWidgets.QTableWidget()
        self.table_lefttop.setObjectName("table_lefttop")
        self.table_lefttop.verticalHeader().setVisible(True)  # 隐藏垂直表头
        self.table_lefttop.horizontalHeader().setVisible(True)  # 隐藏水平表头
        self.table_lefttop.setColumnCount(4)
        self.table_lefttop.setRowCount(0)
        self.table_lefttop.setEditTriggers(QTableView.NoEditTriggers)
        self.table_lefttop.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.table_lefttop.setHorizontalHeaderLabels(
            ['参数', '开始', '结束', '步长'])
        # self.table_lefttop.doubleClicked.connect(self.Function_doubleClicked_strategy)
        self.table_lefttop.setColumnWidth(0, 100)
        self.table_lefttop.setColumnWidth(1, 50)
        self.table_lefttop.setColumnWidth(2, 50)
        self.table_lefttop.setColumnWidth(3, 50)
        self.table_lefttop.setRowHeight(0, 23)
        # self.table_lefttop.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)  # 所有列自动拉伸，充满界面
        self.table_lefttop.setSelectionMode(QAbstractItemView.SingleSelection)  # 设置只能选中一行
        self.table_lefttop.setEditTriggers(QTableView.AllEditTriggers)  # 可编辑
        self.table_leftbottom = QtWidgets.QTableWidget()
        self.table_leftbottom.setObjectName("table_leftbottom")
        self.table_leftbottom.verticalHeader().setVisible(True)  # 隐藏垂直表头
        self.table_leftbottom.horizontalHeader().setVisible(True)  # 隐藏水平表头
        self.table_leftbottom.setColumnCount(5)
        self.table_leftbottom.setRowCount(0)
        self.table_leftbottom.setEditTriggers(QTableView.NoEditTriggers)
        self.table_leftbottom.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.table_leftbottom.setHorizontalHeaderLabels(
            ['', '回测合约', '开始', '结束', '大小'])
        self.table_leftbottom.setRowHeight(0, 28)
        self.table_leftbottom.setColumnWidth(0, 0)
        self.table_leftbottom.setColumnWidth(1, 130)
        self.table_leftbottom.setColumnWidth(2, 80)
        self.table_leftbottom.setColumnWidth(3, 80)
        self.table_leftbottom.setColumnWidth(4, 80)
        self.table_leftbottom.setSelectionMode(QAbstractItemView.NoSelection)  # 设置只能选中一行
        module_backtest.Function_ReadDataList(self.table_leftbottom, True)

        MainWindow = self
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        _translate = QtCore.QCoreApplication.translate
        self.verticalLayout_5 = QtWidgets.QVBoxLayout(self.centralwidget)
        self.verticalLayout_5.setObjectName("verticalLayout_5")
        self.table_thispargroup = QtWidgets.QTableWidget()
        self.table_thispargroup.setSortingEnabled(True)
        self.table_thispargroup.setObjectName("table_thispargroup")
        self.table_thispargroup.setColumnCount(15)
        self.table_thispargroup.setRowCount(0)
        self.table_thispargroup.setEditTriggers(QTableView.NoEditTriggers)
        self.table_thispargroup.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.table_thispargroup.setHorizontalHeaderLabels(
            ['', '操作', '参数1', '参数2', '参数3', '参数4', '参数5', '参数6', '权益', '收益率', '胜率', '盈亏比', '交易次数', '夏普率', '索提诺比率'])
        self.table_thispargroup.setRowHeight(0, 28)
        self.table_thispargroup.setColumnWidth(0, 0)
        self.table_thispargroup.setColumnWidth(1, 60)
        self.table_thispargroup.setColumnWidth(2, 40)
        self.table_thispargroup.setColumnWidth(3, 40)
        self.table_thispargroup.setColumnWidth(4, 40)
        self.table_thispargroup.setColumnWidth(5, 40)
        self.table_thispargroup.setColumnWidth(6, 40)
        self.table_thispargroup.setColumnWidth(7, 40)
        self.table_thispargroup.setColumnWidth(8, 90)
        self.table_thispargroup.setColumnWidth(9, 70)
        self.table_thispargroup.setColumnWidth(10, 70)
        self.table_thispargroup.setColumnWidth(11, 70)
        self.verticalLayout_5.addWidget(self.table_thispargroup)
        self.table_middle = QtWidgets.QTableWidget()
        self.table_middle.setObjectName("table_middle")
        self.table_middle.verticalHeader().setVisible(True)  # 隐藏垂直表头
        self.table_middle.horizontalHeader().setVisible(True)  # 隐藏水平表头
        self.table_middle.setColumnCount(7)
        self.table_middle.setRowCount(0)
        self.table_middle.setEditTriggers(QTableView.NoEditTriggers)
        self.table_middle.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.table_middle.setHorizontalHeaderLabels(['日期', '时间', '合约', '买卖', '开平', '成交价格', '委托手数'])
        self.table_middle.setRowHeight(0, 30)
        self.table_middle.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
        self.table_middle.setSelectionMode(QAbstractItemView.SingleSelection)  # 设置只能选中一行
        self.table_righttop = QtWidgets.QTableWidget()
        self.table_righttop.setObjectName("table_righttop")
        self.table_righttop.verticalHeader().setVisible(True)  # 隐藏垂直表头
        self.table_righttop.horizontalHeader().setVisible(True)  # 隐藏水平表头
        self.table_righttop.setColumnCount(3)
        self.table_righttop.setColumnWidth(0, 200)
        self.table_righttop.setColumnWidth(1, 120)
        self.table_righttop.setColumnWidth(2, 45)
        self.table_righttop.setEditTriggers(QTableView.NoEditTriggers)
        self.table_righttop.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.table_righttop.setHorizontalHeaderLabels(['完成回测的合约', '完成时间', '操作'])
        self.table_righttop.setRowHeight(0, 30)
        # self.table_righttop.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
        self.table_righttop.setSelectionMode(QAbstractItemView.SingleSelection)  # 设置只能选中一行
        self.table_righttop.doubleClicked.connect(self.Function_ReadInstrumentEquityCurve)

        # 资金曲线图
        # self.wincurl = pg.GraphicsLayoutWidget(show=True, size=(400, 250))

        self.wincurl = pg.GraphicsLayoutWidget(show=True)
        self.wincurl.setWindowTitle('回测资金曲线')
        self.plt_realtime = self.wincurl.addPlot(title="回测资金曲线")
        # self.wincurl.setBackground('y')
        # plt_realtime.setAutoVisibleOnly(y=True)
        # o ,t,s
        self.curve_realtime = self.plt_realtime.plot(pen='y')
        self.curve_buy = self.plt_realtime.plot(x=[], y=[], pen=QtGui.QColor(0, 0, 0, 0), symbol='o',
                                                symbolBrush=(255, 0, 0))
        self.curve_sell = self.plt_realtime.plot(x=[], y=[], pen=QtGui.QColor(0, 0, 0, 0), symbol='o',
                                                 symbolBrush=(0, 255, 0))

        # self.x = np.array([1, 2, 3, 4])
        # self.y = np.array([500000, 510000, 610000, 50000])
        # self.curve_sell = self.plt_realtime.plot(self.x, self.y, pen= QtGui.QColor(0,0,0,0), symbolBrush=(0, 255, 0) )

        # self.curve_point = self.plt_realtime.plot(100,pen='r')
        # data = ts.get_hist_data('sh', start='2017-10-01', end='2017-12-01').sort_index()
        # data = {'open':3000,'close':4000}
        # xdict = dict(enumerate(data.index))
        # self.plt_realtime.plot(x=list(xdict.keys()), y=data['open'].values, pen='r', name='开盘指数', symbolBrush=(255, 0, 0), )
        # self.plt_realtime.plot(x=list(xdict.keys()), y=data['close'].values, pen='g', name='收盘指数', symbolBrush=(0, 255, 0))

        self.plt_realtime.setMouseEnabled(x=True, y=True)  # 禁用轴操作
        self.wincurl.showMaximized()
        # 资金曲线图
        self.tab_tableWidget = QtWidgets.QWidget()
        self.tab_tableWidget.setObjectName("tab_tableWidget")
        self.list_backtestlog = QtWidgets.QListWidget(self.tab_tableWidget)
        self.list_backtestlog.setObjectName("list_backtestlog")
        _translate = QtCore.QCoreApplication.translate
        __sortingEnabled = self.list_backtestlog.isSortingEnabled()
        self.list_backtestlog.setSortingEnabled(False)
        self.list_backtestlog.setSortingEnabled(__sortingEnabled)
        self.layout = QtWidgets.QGridLayout(self.tab_tableWidget)
        self.layout.setContentsMargins(0, 0, 0, 0)
        self.layout.setObjectName("layout")
        # 合约任务进度条
        self.taskinstrumentIDBar = QtWidgets.QProgressBar()
        self.taskinstrumentIDBar.setProperty("taskinstrumentIDBar", 0)
        self.taskinstrumentIDBar.setObjectName("taskinstrumentIDBar")
        self.taskinstrumentIDBar.setProperty("value", '0')
        self.taskinstrumentIDBar.setFormat('完成 0%（已完成回测合约数/总合约数 = 0/' + str(self.table_leftbottom.rowCount()) + '）')

        # 合约文件载入进度
        self.taskdataBar = QtWidgets.QProgressBar()
        self.taskdataBar.setProperty("taskdataBar", 0)
        self.taskdataBar.setObjectName("taskdataBar")
        self.taskdataBar.setProperty("value", '0')
        self.taskdataBar.setFormat('数据载入进度 0%')
        # 参数组进度条
        self.taskprogressBar = QtWidgets.QProgressBar()
        self.taskprogressBar.setProperty("taskprogressBar", 0)
        self.taskprogressBar.setObjectName("taskprogressBar")
        self.taskprogressBar.setProperty("value", '0')
        self.taskprogressBar.setFormat('参数组回测任务进度 0%')
        self.comBox_period = QtWidgets.QComboBox()
        self.comBox_period.addItems(['M1', 'M3', 'M5', 'M10', 'M15', 'M30', 'M60', 'M120'])
        self.comBox_period.setCurrentIndex(1)
        self.comBox_slippoint = QtWidgets.QComboBox()
        self.comBox_slippoint.addItems(
            ['滑点按价格1跳', '滑点按价格2跳', '滑点按价格3跳', '滑点按价格4跳', '滑点按价格5跳', '滑点按价格6跳', '滑点按价格7跳', '滑点按价格8跳'])
        self.comBox_slippoint.setCurrentIndex(0)
        self.comBox_process = QtWidgets.QComboBox()
        for k in range(self.maxprocessnum):
            self.comBox_process.addItems(['使用 ' + str(k + 1) + ' 个回测进程'])
        self.comBox_process.setCurrentIndex(self.maxprocessnum - 1)
        self.comBox_adjustment = QtWidgets.QComboBox()
        self.comBox_adjustment.addItems(
            ['不复权', '前复权', '后复权'])
        self.comBox_adjustment.setCurrentIndex(1)
        module = self.dynamic_import('strategyfile.' + self.mainstrategyname)
        self.parnum = len(module.parlist)
        for i in range(self.parnum):
            print("序号：%s   值：%s" % (i + 1, module.parlist[i]))
            self.table_lefttop.insertRow(i)
            # item = QTableWidgetItem('参数' + str(i + 1))
            item = QTableWidgetItem(module.parlist[i][0])
            item.setFlags(QtCore.Qt.ItemIsEnabled)
            self.table_lefttop.setItem(i, 0, item)
            item = QTableWidgetItem(str(module.parlist[i][1]))
            self.table_lefttop.setItem(i, 1, item)
            item = QTableWidgetItem(str(module.parlist[i][2]))
            self.table_lefttop.setItem(i, 2, item)
            item = QTableWidgetItem(str(module.parlist[i][3]))
            self.table_lefttop.setItem(i, 3, item)

        list_tj = ["参数条件：不设置"]
        for i in range(self.parnum):
            for j in range(self.parnum):
                if i != j:
                    if i < j:
                        temp = '参数条件：参数' + str(i + 1) + '<参数' + str(j + 1)
                    else:
                        temp = '参数条件：参数' + str(j + 1) + '>参数' + str(i + 1)
                    list_tj.append(temp)

        self.comBox_conditions0 = QtWidgets.QComboBox()
        self.comBox_conditions1 = QtWidgets.QComboBox()
        self.comBox_conditions2 = QtWidgets.QComboBox()
        dict_comboxconditions = {0: self.comBox_conditions0, 1: self.comBox_conditions1, 2: self.comBox_conditions2}
        for i in range(min(3, self.parnum - 1)):
            print('i：' + str(i))
            dict_comboxconditions[i].addItems(list_tj)
            dict_comboxconditions[i].setCurrentIndex(0)

        dict_ico = {0: 'ico/ico_selectnone.png',
                    1: 'ico/ico_1.png',
                    2: 'ico/ico_2.png',
                    3: 'ico/ico_3.png',
                    4: 'ico/ico_4.png',
                    5: 'ico/ico_5.png',
                    6: 'ico/ico_6.png'}

        self.btn_setvirtualaccount = QPushButton('设置回测账号参数', self)
        self.btn_setvirtualaccount.setIcon(QtGui.QIcon('ico/ico_user.ico'))
        self.btn_setvirtualaccount.clicked.connect(self.OnSetVirtualAccount)

        self.btn_ok = QPushButton('', self)
        # 更新数据显示进程
        self.btn_ok.setCursor(QtGui.QCursor(Qt.PointingHandCursor))
        self.btn_ok.clicked.connect(self.OnStart_BackTest)
        self.btn_ok.setSizePolicy(
            QtGui.QSizePolicy.Fixed, 0)
        self.btn_ok.setStyleSheet("QPushButton{border-image: url(onstartbacktest1.png)}")
        self.btn_ok.setFixedSize(256, 70)
        self.btn_ok.setContentsMargins(0, 0, 0, 0)
        self.btn_selectall = QPushButton('选择全部', self)
        self.btn_selectclearall = QPushButton('清除全部', self)
        # self.btn_openprocesswindow = QPushButton('显示回测进程窗口', self)
        # self.btn_closeprocesswindow = QPushButton('隐藏回测进程窗口', self)
        self.btn_openbacktestkline = QPushButton('回测数据样本K线图（含交易信号）', self)
        self.btn_analysisreport = QPushButton('参数组分析报告', self)
        self.btn_selectall.clicked.connect(self.OnSelectall)
        self.btn_selectclearall.clicked.connect(self.OnSelectclearall)
        self.btn_openbacktestkline.clicked.connect(self.Function_OpenBackTestKline)
        # self.btn_downloaddata.clicked.connect(self.OnDownloadData)
        # self.btn_openprocesswindow.clicked.connect(self.OnOpenProcesswindow)

        self.comBox_refreshfrequency = QtWidgets.QComboBox()
        self.comBox_refreshfrequency.addItems(
            ['回测进程窗口：每1条插入1条记录', '回测进程窗口：每10条插入1条记录', '回测进程窗口：每100条插入1条记录', '回测进程窗口：每500条插入1条记录',
             '回测进程窗口：每1000条插入1条记录', '回测进程窗口：每3000条插入1条记录'])
        self.comBox_refreshfrequency.setCurrentIndex(3)
        self.btn_analysisreport.clicked.connect(self.OnOpenParAnalysisReport)
        self.layout.addWidget(self.table_lefttop, 0, 0, 896, 20)
        self.layout.addWidget(self.comBox_period, 896, 0, 4, 20)
        self.layout.addWidget(self.comBox_slippoint, 900, 0, 4, 20)
        self.layout.addWidget(self.comBox_process, 904, 0, 4, 20)
        self.layout.addWidget(self.comBox_adjustment, 908, 0, 4, 20)
        self.layout.addWidget(self.table_leftbottom, 912, 0, 884, 20)
        self.layout.addWidget(self.btn_selectall, 1796, 2, 4, 8)
        self.layout.addWidget(self.btn_selectclearall, 1796, 10, 4, 8)
        self.layout.addWidget(self.btn_ok, 1800, 0, 200, 20)
        self.layout.addWidget(self.btn_setvirtualaccount, 2, 21, 1, 5)

        for i in range(min(3, self.parnum - 1)):
            self.layout.addWidget(dict_comboxconditions[i], 1, 20 + 6 * (i + 1), 3, 4)
        self.layout.addWidget(self.centralwidget, 4, 20, 1466, 45)
        self.layout.addWidget(self.taskinstrumentIDBar, 1470, 20, 10, 45)
        self.layout.addWidget(self.taskdataBar, 1480, 20, 10, 45)
        self.layout.addWidget(self.taskprogressBar, 1490, 20, 10, 45)
        self.checkbox_curlsetting = QCheckBox('回测时更新资金曲线', self)
        self.layout.addWidget(self.checkbox_curlsetting, 1500, 20, 10, 5)
        self.layout.addWidget(self.comBox_refreshfrequency, 1500, 25, 10, 6)
        self.layout.addWidget(self.btn_openbacktestkline, 1500, 31, 10, 17)
        self.layout.addWidget(self.btn_analysisreport, 1500, 48, 10, 17)
        self.layout.addWidget(self.wincurl, 1510, 20, 490, 45)
        self.layout.addWidget(self.table_righttop, 0, 65, 900, 45)
        self.layout.addWidget(self.list_backtestlog, 900, 65, 600, 45)
        self.layout.addWidget(self.table_middle, 1500, 65, 500, 45)
        self.setLayout(self.layout)
        '''
           #从策略配置文件读取参数设置self.mainstrategyname
           import configparser
           conf = configparser.ConfigParser()
           conf.read('./strategyfile/'+self.mainstrategyname+'.ini')
           sections = conf.sections()
           # 给字典增加key
           for i, j in enumerate(sections):
               options = conf.options(j)
               globalvar.dict_talibcondition[j] = []
               for m, n in enumerate(options):
                   globalvar.dict_talibcondition[j].append(conf.get(j, n))
           '''

    # 信号槽  更新进度条
    def callback_backtest_processbar(self, list):
        globalvar.DialogBackTestPoint.taskprogressBar.setProperty("value", list[0])
        globalvar.DialogBackTestPoint.taskprogressBar.setFormat(list[1])

    # 更新进度条
    def UpdateProcessbar(self, diffsecond, instrumentname):
        try:
            if False:
                # if globalvar.DialogBackTestPoint.closestate == True:
                globalvar.finishtasknum = globalvar.finishtasknum + 1
                return
            # globalvar.finishtasknum = globalvar.finishtasknum + 1
            if globalvar.totaltasknum == 0:
                return
            if globalvar.totaltasknum > 0:
                rate = float(globalvar.finishtasknum) / float(globalvar.totaltasknum)
                # diffsecond = (datetime.now() - self.starttime).seconds
                h = int(diffsecond / 3600)
                m = int((diffsecond - h * 3600) / 60)
                s = diffsecond - h * 3600 - m * 60
                if rate > 0:
                    leftsecond = int(float(diffsecond) * ((1.0 - rate) / rate))
                else:
                    leftsecond = 0
                h2 = int(leftsecond / 3600)
                m2 = int((leftsecond - h2 * 3600) / 60)
                s2 = leftsecond - h2 * 3600 - m2 * 60
                usertime = "耗时%d:%02d:%02d 完成倒计时%d:%02d:%02d" % (h, m, s, h2, m2, s2)
                thisvalue = float(100 * rate)
                formattext = instrumentname + "参数组回测任务进度 %p% (" + str(globalvar.finishtasknum) + "\\" + str(
                    globalvar.totaltasknum) + ")" + usertime
                self.callback_backtest_processbar([thisvalue, formattext])
        except Exception as e:
            print('OnFinish error:', e)

    # 添加交易记录显示
    def AddTradingRecordShow(self, filename):
        if os.path.isfile(filename):
            datalist = []
            dict_tradingday_buy = {}
            dict_tradingday_sell = {}
            self.table_middle.clear()
            self.table_middle.setRowCount(0)
            self.table_middle.setHorizontalHeaderLabels(['日期', '时间', '合约', '买卖', '开平', '成交价格', '委托手数'])
            with open(filename, 'r') as f:
                for line in f:
                    datalist = line.strip('\n').split(',')
                    row_cnt = globalvar.DialogBackTestPoint.table_middle.rowCount()  # 返回当前行数（尾部）
                    globalvar.DialogBackTestPoint.table_middle.insertRow(row_cnt)  # 尾部插入一行新行表格
                    item = QTableWidgetItem(datalist[0])
                    globalvar.DialogBackTestPoint.table_middle.setItem(row_cnt, 0, item)
                    item = QTableWidgetItem(datalist[1])
                    globalvar.DialogBackTestPoint.table_middle.setItem(row_cnt, 1, item)
                    item = QTableWidgetItem(datalist[2])
                    globalvar.DialogBackTestPoint.table_middle.setItem(row_cnt, 2, item)
                    item = QTableWidgetItem(datalist[3])
                    globalvar.DialogBackTestPoint.table_middle.setItem(row_cnt, 3, item)
                    item = QTableWidgetItem(datalist[4])
                    globalvar.DialogBackTestPoint.table_middle.setItem(row_cnt, 4, item)
                    item = QTableWidgetItem(datalist[5])
                    globalvar.DialogBackTestPoint.table_middle.setItem(row_cnt, 5, item)
                    item = QTableWidgetItem(datalist[6])
                    globalvar.DialogBackTestPoint.table_middle.setItem(row_cnt, 6, item)
                    # list_tradingday_buy.append(datalist[0]+datalist[1])
                    # list_tradingday_sell.append(datalist[0] + datalist[1])
                    if len(datalist[1]) == 5:
                        datalist[1] = '0' + datalist[1]
                    if datalist[3] == '买':
                        dict_tradingday_buy[datalist[0] + datalist[1]] = True
                    else:
                        dict_tradingday_sell[datalist[0] + datalist[1]] = True
            return [dict_tradingday_buy, dict_tradingday_sell]
        else:
            return []

    # 信号槽  返回回测结果
    def callback_backtest_result(self, arg):
        processid = -1
        try:
            processid = self.dict_processid[str(arg[2])]
        except Exception as e:
            self.dict_processid[str(arg[2])] = len(self.dict_processid)
            processid = self.dict_processid[str(arg[2])]
        self.UpdateProcessbar(int(arg[1]), str(arg[0][2]))
        globalvar.DialogBackTestPoint.table_thispargroup.insertRow(0)  # 插入一行新行表格
        item = QTableWidgetItem(str(arg[0][2]))
        globalvar.DialogBackTestPoint.table_thispargroup.setItem(0, 0, item)
        deleteButton1 = QPushButton("图表")
        deleteButton1.clicked.connect(globalvar.DialogBackTestPoint.Function_UpdateEquityCurveForButton)
        globalvar.DialogBackTestPoint.table_thispargroup.setCellWidget(0, 1, deleteButton1)
        item = QTableWidgetItem(str(arg[0][0][0]))
        globalvar.DialogBackTestPoint.table_thispargroup.setItem(0, 2, item)
        item = QTableWidgetItem(str(arg[0][0][1]))
        globalvar.DialogBackTestPoint.table_thispargroup.setItem(0, 3, item)
        item = QTableWidgetItem(str(arg[0][0][2]))
        globalvar.DialogBackTestPoint.table_thispargroup.setItem(0, 4, item)
        item = QTableWidgetItem(str(arg[0][0][3]))
        globalvar.DialogBackTestPoint.table_thispargroup.setItem(0, 5, item)
        item = QTableWidgetItem(str(arg[0][0][4]))
        globalvar.DialogBackTestPoint.table_thispargroup.setItem(0, 6, item)
        item = QTableWidgetItem(str(arg[0][0][5]))
        globalvar.DialogBackTestPoint.table_thispargroup.setItem(0, 7, item)
        item = QTableWidgetItem(str(arg[0][1][0]))
        globalvar.DialogBackTestPoint.table_thispargroup.setItem(0, 8, item)
        item = QTableWidgetItem(str(arg[0][1][1]) + '%')
        globalvar.DialogBackTestPoint.table_thispargroup.setItem(0, 9, item)
        item = QTableWidgetItem(str(arg[0][1][2]))
        globalvar.DialogBackTestPoint.table_thispargroup.setItem(0, 10, item)
        item = QTableWidgetItem(str(arg[0][1][3]))
        globalvar.DialogBackTestPoint.table_thispargroup.setItem(0, 11, item)
        item = QTableWidgetItem(str(arg[0][1][4]))
        globalvar.DialogBackTestPoint.table_thispargroup.setItem(0, 12, item)
        item = QTableWidgetItem(str(arg[0][1][5]))
        globalvar.DialogBackTestPoint.table_thispargroup.setItem(0, 13, item)
        item = QTableWidgetItem(str(arg[0][1][6]))
        globalvar.DialogBackTestPoint.table_thispargroup.setItem(0, 14, item)

        tempstr = str(arg[0][0][0]) + '_' + str(
            arg[0][0][1]) + '_' + str(
            arg[0][0][2]) + '_' + str(arg[0][0][3]) + '_' + str(arg[0][0][4]) + '_' + str(arg[0][0][5]) + '.txt'
        filename_tradingrecord = str(arg[0][2]) + '/tradingrecord/' + tempstr
        list_tradingday = self.AddTradingRecordShow(filename_tradingrecord)
        # if self.selectbacktestcurl:
        # self.Function_UpdateEquityCurve()
        # return
        if False:
            filename_curl = str(arg[0][2]) + '/' + tempstr
            self.Function_UpdateEquityCurveByFileName(filename_curl, list_tradingday)
            '''
               return
               try:
                   globalvar.ui_bt.Function_UpdateEquityCurveByFileName2(filename_curl, list_tradingday)
                   globalvar.ui_bt.UpdateTable(arg)
                   pass
               except Exception as e:
                   print("callback_backtest_loaddata Error:" + repr(e)
               '''

    # 信号槽  返回加载数据状态
    def callback_backtest_loaddata(self, list):
        try:
            if list[0] == 1:
                thisvalue = 100 * float(list[2])
                globalvar.DialogBackTestPoint.taskdataBar.setProperty("value", thisvalue)
                globalvar.DialogBackTestPoint.taskdataBar.setFormat(
                    str(list[3]) + " 加载到内存进度 %p% （已读取" + str(list[1]) + '行）')
            else:
                thisvalue = 100 * float(list[2])
                globalvar.DialogBackTestPoint.taskdataBar.setProperty("value", thisvalue)
                globalvar.DialogBackTestPoint.taskdataBar.setFormat(
                    " 转换周期数据为" + str(list[3]) + "周期，已转换 %p% （" + str(list[1]) + '行）')
            '''
               globalvar.DialogBackTestPoint.progressbarlist[list[0]].setProperty("value", list[1])
               globalvar.DialogBackTestPoint.progressbarlist[list[0]].setFormat(list[2])
               if list[1] == 100:
                   globalvar.DialogBackTestPoint.progressbarlist[list[0]].setProperty("value", 0)
                   globalvar.DialogBackTestPoint.progressbarlist[list[0]].setFormat("回测进程等待")
               '''
        except Exception as e:
            print("callback_backtest_loaddata Error:" + repr(e))

    # 信号槽  返回单次回测结果
    def callback_backtest_addresult(self, result):
        print("callback_backtest_addresult")
        # row_cnt = self.table_righttop.rowCount()  # 返回当前行数（尾部
        self.table_righttop.insertRow(0)  # 插入一行新行表格
        self.finishnum += 1
        filename = result[0][2].replace('backtestreport/', '')
        filename = filename.replace(globalvar.DialogBackTestPoint.mainstrategyname + '/', '')
        item = QTableWidgetItem(filename)
        self.table_righttop.setItem(0, 0, item)
        now = time.strftime("%Y-%m-%d %H:%M", time.localtime())
        item = QTableWidgetItem(now)
        self.table_righttop.setItem(0, 1, item)
        deleteButton2 = QPushButton("报告")
        deleteButton2.clicked.connect(self.Function_ReadInstrumentEquityCurveForButton)

        # item.connect(self.table_algorithmtrading, QtCore.SIGNAL("itemClicked(QTableWidgetItem*)"),
        #             self.function_item_clicked)

        self.table_righttop.setCellWidget(0, 2, deleteButton2)
        # finishnum = self.finishnum #table_righttop.rowCount()
        totalnum = self.table_leftbottom.rowCount()
        thisvalue = 100 * float(self.finishnum / totalnum)
        self.taskinstrumentIDBar.setProperty("value", thisvalue)
        self.taskinstrumentIDBar.setFormat(
            '完成 %p%（已完成回测合约数/总合约数 = ' + str(self.finishnum) + '/' + str(totalnum) + '）')

    # 信号槽
    def callback_backtest_adjustmentprice(self, list):
        try:
            thisvalue = 100 * float(list[1])
            globalvar.DialogBackTestPoint.taskdataBar.setProperty("value", thisvalue)
            globalvar.DialogBackTestPoint.taskdataBar.setFormat(
                str(list[2]) + "，已复权 %p% （" + str(list[0]) + '行）')
        except Exception as e:
            print("callback_backtest_adjustmentprice Error:" + repr(e))

    # 选择所有
    def OnSelectall(self):
        for i in range(self.table_leftbottom.rowCount()):
            self.table_leftbottom.item(i, 1).setCheckState(2)
            '''
               if self.table_leftbottom.item(i, 1).checkState():
                   temp = self.table_leftbottom.item(i, 1).text()
                   print('读取文件： ' + temp)
                   self.csvfile.append(self.table_leftbottom.item(i, 1).text())
               '''

    # 全部不选
    def OnSelectclearall(self):
        for i in range(self.table_leftbottom.rowCount()):
            self.table_leftbottom.item(i, 1).setCheckState(0)

    # 设置回测用的虚拟账号
    def OnSetVirtualAccount(self):
        messagebox = QMessageBox()
        messagebox.setWindowTitle('提示')
        messagebox.setText('回测用虚拟账号默认资金50万,暂时不可修改！\n\n请耐心等待功能升级！')
        messagebox.setStandardButtons(QMessageBox.Yes)
        buttonY = messagebox.button(QMessageBox.Yes)
        buttonY.setText('确定')
        reply = messagebox.exec_()
        if messagebox.clickedButton() == buttonY:
            pass
        return

    # https: // www.cnblogs.com / yzh2857 / p / 9683398.html

    def OnCloseProcesswindow(self):
        # 回测窗口关闭事件
        try:
            globalvar.pipe1.close()
            globalvar.pipe0.send('hide')
            globalvar.pipe0.send('hide')
            globalvar.pipe0.send('hide')
            globalvar.pipe0.send('hide')
            globalvar.pipe0.close()
        except Exception as e:
            pass

    # 根据strategyfile目录下实盘策略文件生成回测用额策略文件
    def GenerateBackTestFile(self):
        filename = self.strategyname
        filename2 = filename.replace('strategyfile', 'strategyfilebacktest')
        grouplist = []
        tempstr = ''
        if os.path.exists(filename2):  # 如果文件存在
            # 删除文件，可使用以下两种方法。
            os.remove(filename2)
        with open(filename, 'rb') as f:
            for line in f:
                line2 = str(line)
                line2 = line2.replace(', ', ',')
                line2 = line2.replace(',  ', ',')
                line2 = line2.replace(',   ', ',')
                lintkeep = True
                # if tempstr == '':
                pos = line2.find('def __init__(self')
                if pos >= 0:
                    continue
                pos = line2.find('super(MyStrategy,self).__init__(period,slippoint)')
                if pos >= 0:
                    lintkeep = False
                    temp = ''
                    for i in range(pos - 2):
                        temp = temp + ' '
                    with open(filename2, "a") as h:
                        h.write("    def __init__(self, period, slippoint):\n")
                        h.write(temp + "super(MyStrategy,self).__init__(period,slippoint)\n")
                        h.write(temp + "self.TradingDay = []\n")
                        h.write(temp + "self.klinetime = []\n")
                        h.write(temp + "self.volume = []\n")
                        h.write(temp + "self.money = []\n")
                        h.write(temp + "self.open_interest = []\n")
                        h.write(temp + "self.InstrumentID = []\n")
                    continue

                pos = line2.find('InsertOrder2')
                if pos >= 0:
                    lintkeep = False
                    temp = ''
                    for i in range(pos - 2):
                        temp = temp + ' '
                    with open(filename2, "a") as h:
                        h.write(
                            temp + "self.InsertOrder_backtest(InstrumentID, exchangeid, direction, offside, orderpricetype, price, vol)\n")
                    continue

                pos = line2.find('def OnKline')
                if pos >= 0:
                    lintkeep = False
                    if pos >= 0:
                        tempstr = ''
                        for i in range(pos - 2):
                            tempstr = tempstr + ' '
                    with open(filename2, "a") as h:
                        h.write(
                            '    def OnKline(self, reportpath1, reportpath2, kdata, arg, strategyname, filter):\n')
                        h.write(
                            tempstr + '    super(MyStrategy, self).OnKline(reportpath1, reportpath2, arg, kdata, filter)\n')
                    continue
                if lintkeep:
                    with open(filename2, "ab") as h:
                        h.write(line)

    # 打开回测参数分析报告
    def OnOpenParAnalysisReport(self):
        print('OnOpenParAnalysisReport')
        '''window = module_backtestreport.LingBrowser()
           window.show()

           try:
               row_cnt = self.table_thispargroup.rowCount()  # 返回当前行数（尾部）
               if row_cnt == 0:
                   return
               temp = self.table_thispargroup.item(0, 0).text().split('/')
               str = temp[0] + '/' + temp[1] + '/' + temp[2] + '/' + 'resultlist.csv'
               # print(str)
               # print(self.mainstrategyname)
               # ui_demo = globalvar.ui.DialogParAnalysisReport('backtestreport/'+self.mainstrategyname, '')
               ui_demo = globalvar.ui.DialogParAnalysisReport(str, temp[3])
               screen = QDesktopWidget().screenGeometry()
               size = ui_demo.geometry()
               ui_demo.move((screen.width() - size.width()) / 2 - 180,
                            (screen.height() - size.height()) / 2)
               ui_demo.setWindowTitle('回测分析报告' + str)
               ui_demo.show()
               ui_demo.resize(1024, 600)
               # self.childwidget = self.childwidget(self)
               ui_demo.exec_()
           except Exception as e:
               print("OnOpenParAnalysisReport Error:" + repr(e))
           '''

    def OnStart_BackTest(self):
        sbt = threading.Thread(target=self.OnStart_BackTest2, name='OnStart_BackTest2')
        sbt.start()

    def OnStart_BackTest2(self):
        if globalvar.backteststate == 1:
            # 停止回测
            globalvar.backteststate = 0
            self.closestate = True

            self.bt.OnStop('停止回测')
            globalvar.DialogBackTestPoint.OnCloseProcesswindow()
            globalvar.manager.shutdown()
            globalvar.pool.close()
        elif globalvar.backteststate == 0:
            globalvar.DialogBackTestPoint.taskdataBar.setProperty("value", 0)
            globalvar.DialogBackTestPoint.taskdataBar.setFormat("数据载入进度 0%")
            # 根据实盘策略文件生成回测用的策略文件格式
            self.GenerateBackTestFile()
            '''
               if self.suffix == ".pyd":
                   print("pyd文件无法直接转化回测文件")
               elif self.suffix == ".py":
                   self.GenerateBackTestFile()
               elif self.suffix == ".pyc" or self.suffix == ".pyo":
                   print("pyc或pyo文件无法直接转化回测文件")
               '''
            # 获取数据文件
            self.csvfile = []
            for i in range(self.table_leftbottom.rowCount()):
                if self.table_leftbottom.item(i, 1).checkState():
                    temp = self.table_leftbottom.item(i, 1).text()
                    print('读取文件： ' + temp)
                    self.csvfile.append(self.table_leftbottom.item(i, 1).text())
            if len(self.csvfile) == 0:
                messagebox = QMessageBox()
                messagebox.setWindowTitle('提示')
                messagebox.setText('请至少选中1个数据文件')
                messagebox.setStandardButtons(QMessageBox.Yes)
                buttonY = messagebox.button(QMessageBox.Yes)
                buttonY.setText('确定')
                reply = messagebox.exec_()
                return
            # 开始回测
            globalvar.backteststate = 1
            processnum = globalvar.DialogBackTestPoint.comBox_process.currentIndex() + 1
            conditions0 = globalvar.DialogBackTestPoint.comBox_conditions0.currentText()
            conditions1 = globalvar.DialogBackTestPoint.comBox_conditions1.currentText()
            conditions2 = globalvar.DialogBackTestPoint.comBox_conditions2.currentText()
            adjustment = globalvar.DialogBackTestPoint.comBox_adjustment.currentText()
            dict_refreshfrequency = {0: 1, 1: 10, 2: 100, 3: 500, 4: 1000, 5: 3000}
            refreshfrequency = dict_refreshfrequency[
                globalvar.DialogBackTestPoint.comBox_refreshfrequency.currentIndex()]
            # globalvar.BackTestThreadPoint.pardict.clear()
            self.table_middle.clear()
            self.table_middle.setRowCount(0)
            self.table_middle.setHorizontalHeaderLabels(['日期', '时间', '合约', '买卖', '开平', '成交价格', '委托手数'])
            self.progressbarlist.clear()
            self.bt = module_backtest.BackTestThread()
            # self.bt.signal_backtest_processbar.connect(
            #    globalvar.DialogBackTestPoint.callback_backtest_processbar)  # 进程连接回传到GUI的事件

            self.bt.signal_backtest_result.connect(
                globalvar.DialogBackTestPoint.callback_backtest_result)  # 进程连接回传到GUI的事件
            self.bt.signal_backtest_loaddata.connect(
                globalvar.DialogBackTestPoint.callback_backtest_loaddata)  # 预处理数据
            self.bt.signal_backtest_addresult.connect(
                globalvar.DialogBackTestPoint.callback_backtest_addresult)  # 增加某一个完成回测的合约记录
            self.bt.signal_backtest_adjustmentprice.connect(
                globalvar.DialogBackTestPoint.callback_backtest_adjustmentprice)  # 复权
            # self.bt.start()
            self.bt.fileid = 0
            globalvar.DialogBackTestPoint.finishnum = 0
            self.taskinstrumentIDBar.setProperty("value", '0')
            self.taskinstrumentIDBar.setFormat(
                '完成 0%（已完成回测合约数/总合约数 = 0/' + str(self.table_leftbottom.rowCount()) + '）')
            # multiprocessing.Process(group=None, target=self.bt.OnStart, args=(
            # self.parnum, refreshfrequency, adjustment, conditions0, conditions1, conditions2,))
            self.bt.OnStart(self.parnum, refreshfrequency, adjustment, conditions0, conditions1, conditions2)
        else:
            globalvar.BackTestThreadPoint.OnStopAndNext(0)

    def OnStart_Next(self, fileid):
        self.callback_backtest_processbar([0, '数据载入进度%p%'])
        # 获取数据文件
        self.csvfile = []
        for i in range(self.table_leftbottom.rowCount()):
            if self.table_leftbottom.item(i, 1).checkState():
                temp = self.table_leftbottom.item(i, 1).text()
                print('读取文件： ' + temp)
                self.csvfile.append(self.table_leftbottom.item(i, 1).text())
        if len(self.csvfile) == 0:
            messagebox = QMessageBox()
            messagebox.setWindowTitle('提示')
            messagebox.setText('请至少选中1个数据文件')
            messagebox.setStandardButtons(QMessageBox.Yes)
            buttonY = messagebox.button(QMessageBox.Yes)
            buttonY.setText('确定')
            reply = messagebox.exec_()
            return
        # 开始回测
        globalvar.backteststate = 1
        processnum = globalvar.DialogBackTestPoint.comBox_process.currentIndex() + 1
        conditions0 = globalvar.DialogBackTestPoint.comBox_conditions0.currentText()
        conditions1 = globalvar.DialogBackTestPoint.comBox_conditions1.currentText()
        conditions2 = globalvar.DialogBackTestPoint.comBox_conditions2.currentText()
        adjustment = globalvar.DialogBackTestPoint.comBox_adjustment.currentText()
        refreshfrequency = globalvar.DialogBackTestPoint.comBox_refreshfrequency.currentIndex() + 1

        # globalvar.BackTestThreadPoint.pardict.clear()
        self.table_middle.clear()
        self.table_middle.setRowCount(0)
        self.table_middle.setHorizontalHeaderLabels(['日期', '时间', '合约', '买卖', '开平', '成交价格', '委托手数'])
        self.progressbarlist.clear()
        self.bt = module_backtest.BackTestThread()
        # self.bt.signal_backtest_processbar.connect(
        #    globalvar.DialogBackTestPoint.callback_backtest_processbar)  # 进程连接回传到GUI的事件
        self.bt.signal_backtest_result.connect(
            globalvar.DialogBackTestPoint.callback_backtest_result)  # 进程连接回传到GUI的事件
        self.bt.signal_backtest_loaddata.connect(
            globalvar.DialogBackTestPoint.callback_backtest_loaddata)  # 预处理数据
        self.bt.signal_backtest_addresult.connect(
            globalvar.DialogBackTestPoint.callback_backtest_addresult)  # 增加某一个完成回测的合约记录
        self.bt.signal_backtest_adjustmentprice.connect(
            globalvar.DialogBackTestPoint.callback_backtest_adjustmentprice)  # 复权
        # self.bt.start()
        self.bt.OnStartNext(self.parnum, refreshfrequency, adjustment, conditions0, conditions1, conditions2,
                            fileid)


# 为策略选中交易合约组窗口
class DialogSetInstrumentID(QtWidgets.QDialog):
    def __init__(self, strategyname):
        super().__init__()
        self.strategyname = strategyname
        self.strategynameini = os.path.splitext(strategyname)[0] + '.ini'
        self.setWindowTitle('合约组列表：' + self.strategyname)
        self.setWindowIcon(QIcon('ico/ico_doc.ico'))
        self.InitUI()

    def closeEvent(self, event):
        globalvar.DialogSetInstrumentState = False

    # 扫描合约组设置
    dict_instrumentgroup = {}
    deleteButtonlist = []

    # 从文件读取合约组信息
    def ReadInstrumentIDGroupInfo(self, filename):
        grouplist = []
        with open(filename, 'r') as f:
            for line in f:
                grouplist = line.strip('\n').split(',')
        return len(grouplist)

    # 改变checkbox，自动存储合约组文件名到该策略配置文件
    def OnCellChanged(self, row, column):
        if self.initOnCellChanged:
            return
        LastStateRole = QtCore.Qt.UserRole
        item = self.tableWidget.item(row, column)
        lastState = item.data(LastStateRole)
        currentState = item.checkState()
        if currentState != lastState:
            try:
                csvfile = self.tableWidget.item(row, 1).text().replace('instrumentgroup\\', '')
                if currentState == QtCore.Qt.Checked:
                    if not csvfile in self.csvfiles:
                        self.csvfiles = self.csvfiles + ',' + csvfile.replace('instrumentgroup\\', '')
                        self.csvfiles = self.csvfiles.replace(',,', ',')
                else:
                    if csvfile in self.csvfiles:
                        self.csvfiles = self.csvfiles.replace(csvfile, '').replace(',,', ',')

                csvfilelist = self.csvfiles.split(',')
                csvstr = ''
                lens = len(csvfilelist)
                for id in range(lens):
                    if not csvfilelist[id] == '':
                        if csvstr == '':
                            csvstr = csvfilelist[id]
                        else:
                            csvstr = csvfilelist[id] + ',' + csvstr
                if csvstr != '':
                    global config
                    config = configparser.ConfigParser()
                    config.read(self.strategynameini, encoding="utf-8")  # 读取文件
                    config.set("setting", "groupfile", csvstr)
                    config.write(open(self.strategynameini, mode="w"))
            except Exception as e:
                pass

    def Function_EditInstrumentID(self):
        button = globalvar.ui.MainWindow.sender()
        if button:
            row = globalvar.ui.table_instrumentgroup.indexAt(button.pos()).row()
            filename = globalvar.ui.table_instrumentgroup.item(row, 1).text()
            module_instrumentgroup.Function_EditInstrumentIDByStr(filename)

    # 读取策略的合约组配置文件，设置勾选状态
    def Function_ScanInstrumentIDGroupDlg(self):
        self.initOnCellChanged = True
        path = "instrumentgroup"
        ls = os.listdir(path)
        buttonid = 0
        for i in ls:
            c_path = os.path.join(path, i)
            if os.path.isdir(c_path):
                globalvar.ui.ClearPath(c_path, ".txt")
            else:
                file = os.path.splitext(c_path)
                filename, type = file
                if type == ".csv":
                    try:
                        filenameini = c_path
                        filenameini = filenameini.replace('py', 'ini')
                        self.dict_instrumentgroup[c_path] = globalvar.ui.fileTime(c_path)
                        row_cnt = self.tableWidget.rowCount()  # 返回当前行数（尾部）
                        self.tableWidget.insertRow(row_cnt)  # 尾部插入一行新行表格
                        column_cnt = self.tableWidget.columnCount()  # 返回当前列数
                        item = QTableWidgetItem(str(row_cnt + 1))
                        self.tableWidget.setItem(row_cnt, 0, item)
                        item = QTableWidgetItem(str(c_path))
                        self.tableWidget.setItem(row_cnt, 1, item)
                        item = QTableWidgetItem(str(self.ReadInstrumentIDGroupInfo(str(c_path))))
                        self.tableWidget.setItem(row_cnt, 2, item)
                        item = QTableWidgetItem('备注')
                        self.tableWidget.setItem(row_cnt, 3, item)
                        item = QTableWidgetItem('选择合约组')
                        #  实例化configParser对象
                        config = configparser.ConfigParser()
                        config.read(self.strategynameini, encoding='utf-8')
                        try:
                            self.csvfiles = config.get('setting', 'groupfile')  # 'instrumentgroup\\' +
                            c_path2 = c_path.replace('instrumentgroup\\', '')
                            if c_path2 in self.csvfiles:
                                item.setCheckState(QtCore.Qt.Checked)
                            else:
                                item.setCheckState(QtCore.Qt.Unchecked)
                        except Exception as e:
                            item.setCheckState(QtCore.Qt.Unchecked)
                        self.tableWidget.cellChanged.connect(self.OnCellChanged)
                        self.tableWidget.setItem(row_cnt, 4, item)
                        self.deleteButton = QPushButton("编辑合约组" + str(i))
                        self.deleteButtonlist.append(self.deleteButton)
                        self.deleteButton.clicked.connect(self.Function_EditInstrumentID)
                        buttonid = buttonid + 1
                        self.tableWidget.setCellWidget(row_cnt, 5, self.deleteButton)
                    except Exception as e:
                        print("Function_ScanInstrumentIDGroupDlg Error:" + repr(e))
        self.initOnCellChanged = False

    def InitUI(self):
        self.setWindowFlags(QtCore.Qt.Dialog | QtCore.Qt.WindowStaysOnBottomHint | QtCore.Qt.WindowCloseButtonHint)
        self.layout = QHBoxLayout()
        self.btn_left = QPushButton('选中全部主力合约', self)
        self.btn_right = QPushButton('清空合约', self)
        self.tableWidget = QtWidgets.QTableWidget()
        self.tableWidget.setObjectName("tableWidget")
        self.tableWidget.verticalHeader().setVisible(False)  # 隐藏垂直表头
        self.tableWidget.horizontalHeader().setVisible(True)  # 隐藏水平表头
        self.tableWidget.setColumnCount(6)
        self.tableWidget.setRowCount(0)
        self.tableWidget.setEditTriggers(QTableView.NoEditTriggers)
        self.tableWidget.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.tableWidget.setHorizontalHeaderLabels(
            ['ID', '合约组名称', '选入合约数量', '备注', '操作1', '操作2'])
        self.tableWidget.setColumnWidth(0, 60)
        self.tableWidget.setColumnWidth(1, 220)
        self.tableWidget.setColumnWidth(2, 120)
        self.tableWidget.setColumnWidth(3, 120)
        self.tableWidget.setColumnWidth(4, 120)
        self.tableWidget.setColumnWidth(5, 200)
        self.tableWidget.setRowHeight(0, 30)
        self.tableWidget.setSelectionMode(QAbstractItemView.SingleSelection)  # 设置只能选中一行
        self.tab_tableWidget = QtWidgets.QWidget()
        self.tab_tableWidget.setObjectName("tab_tableWidget")
        self.layout = QtWidgets.QGridLayout(self.tab_tableWidget)
        self.layout.setContentsMargins(0, 0, 0, 0)
        self.layout.setObjectName("gridLayout_strategy")
        # self.tableWidget.setCellWidget(0, 8, Trade_BacktestingBtn)
        self.layout.addWidget(self.tableWidget, 0, 0, 1, 1)
        self.setLayout(self.layout)
        self.Function_ScanInstrumentIDGroupDlg()
        try:
            for i in range(len(globalvar.dict_talibcondition[self.strategyname])):
                item = QTableWidgetItem(' 启用该条件')
                if globalvar.dict_talibcondition[self.strategyname][i][1] == 1:
                    item.setCheckState(QtCore.Qt.Checked)
                else:
                    item.setCheckState(QtCore.Qt.Checked)
                self.tableWidget.setItem(i, 0, item)
                item = QTableWidgetItem(globalvar.dict_talibcondition[self.strategyname][i][2])
                self.tableWidget.setItem(i, 1, item)
                item = QTableWidgetItem(globalvar.dict_talibcondition[self.strategyname][i][3])
                self.tableWidget.setItem(i, 2, item)
                item = QTableWidgetItem(globalvar.dict_talibcondition[self.strategyname][i][4])
                self.tableWidget.setItem(i, 3, item)
        except Exception as e:
            print("Function_ScanInstrumentIDGroupDlg Error:" + repr(e))

    def showDialog(self):
        text, ok = QInputDialog.getText(self, '选择期货公司自动确认brokeid和ip',
                                        '选择期货公司:')
        if ok:
            self.le.setText(str(text))


# 编辑合约组里的合约窗口
class DialogEditInstrumentID(QtWidgets.QDialog):
    def __init__(self, filename):
        super().__init__()
        self.filename = filename
        self.setWindowIcon(QIcon('ico/ico_doc.ico'))
        self.InitUI()

    def closeEvent(self, event):
        globalvar.DialogSetInstrumentState = False

    readfinish = False
    # 保存已经生效的合约
    dict_EnableInstrumentID = {}

    # 读取股票图表访问历史列表
    def ReadInstrumentIDGroup(self):
        returnvalue = False
        with open(self.filename, 'r') as f:
            for line in f:
                enablelist = line.strip('\n').split(',')
                if len(enablelist) > 0:
                    for j in range(len(enablelist)):
                        _translate = QtCore.QCoreApplication.translate
                        item = QtWidgets.QListWidgetItem()
                        self.list_instrumentidgroupselect.addItem(item)
                        item = self.list_instrumentidgroupselect.item(
                            self.list_instrumentidgroupselect.count() - 1)
                        item.setText(_translate("MainWindow", enablelist[j]))
                        self.dict_EnableInstrumentID[enablelist[j]] = True
                    returnvalue = True
                else:
                    returnvalue = False
            self.readfinish = True
        return returnvalue

    # 选入合约（更新显示，更新文件，更新内存变量）
    def AddAndUpdateInstrumentIDGroupFile(self, InstrumentID):
        _translate = QtCore.QCoreApplication.translate
        item = QtWidgets.QListWidgetItem()
        self.list_instrumentidgroupselect.addItem(item)
        item = self.list_instrumentidgroupselect.item(self.list_instrumentidgroupselect.count() - 1)
        item.setText(_translate("MainWindow", InstrumentID))
        self.dict_EnableInstrumentID[InstrumentID] = True
        with open(self.filename, 'r') as f:
            for line in f:
                line = line + ',' + InstrumentID
                with open(self.filename, "w") as f:
                    f.write(line)
                return

    # 删除合约（更新显示，更新文件，更新内存变量）
    def RemoveAndUpdateInstrumentIDGroupFile(self, InstrumentID):
        with open(self.filename, 'r') as f:
            for line in f:
                line = line.replace(InstrumentID, '')
                line = line.replace(',,', ',')
                print(line)
                if line[-1] == ',':
                    line = line[:-1]
                print(line)
                if line[0] == ',':
                    line = line[1:]
                print(line)
                with open(self.filename, "w") as f:
                    f.write(line)
                continue
        self.dict_EnableInstrumentID.clear()
        self.list_instrumentidgroupselect.clear()
        self.ReadInstrumentIDGroup()

    # checkbox改变事件，选入合约或删除合约
    def OnCellChanged(self, row, column):
        LastStateRole = QtCore.Qt.UserRole
        if self.readfinish:
            if column != 3:
                return
            item = self.tableWidget.item(row, column)
            lastState = item.data(LastStateRole)
            currentState = item.checkState()
            if currentState != lastState:
                AddInstrumentID = globalvar.ui.table_instrument.item(row, 2).text()
                if currentState == QtCore.Qt.Checked:
                    self.AddAndUpdateInstrumentIDGroupFile(AddInstrumentID)
                else:
                    self.RemoveAndUpdateInstrumentIDGroupFile(AddInstrumentID)
                item.setData(LastStateRole, currentState)

    def InitUI(self):
        self.setWindowFlags(QtCore.Qt.Dialog | QtCore.Qt.WindowStaysOnBottomHint | QtCore.Qt.WindowCloseButtonHint)
        self.tableWidget = QTableWidget()
        self.layout = QHBoxLayout()
        self.btn_left = QPushButton('', self)
        self.btn_right = QPushButton('', self)
        row_cnt = globalvar.ui.table_instrument.rowCount()
        self.tableWidget.setObjectName("setinstrument")
        self.tableWidget.verticalHeader().setVisible(True)  # 隐藏垂直表头
        self.tableWidget.horizontalHeader().setVisible(True)  # 隐藏水平表头
        self.tableWidget.setEditTriggers(QTableView.NoEditTriggers)
        self.tableWidget.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.tableWidget.setColumnCount(4)
        self.tableWidget.setRowCount(row_cnt)
        self.tableWidget.setHorizontalHeaderLabels(
            ['合约', '合约代码', '交易所', '加入'])
        self.tableWidget.setSortingEnabled(True)  # 设置表头可以自动排序
        self.tab_tableWidget = QtWidgets.QWidget()
        self.tab_tableWidget.setObjectName("tab_tableWidget")
        self.list_instrumentidgroupselect = QtWidgets.QListWidget(self.tab_tableWidget)
        self.list_instrumentidgroupselect.setObjectName("list_instrumentidgroupselect")
        _translate = QtCore.QCoreApplication.translate
        __sortingEnabled = self.list_instrumentidgroupselect.isSortingEnabled()
        self.list_instrumentidgroupselect.setSortingEnabled(False)
        self.list_instrumentidgroupselect.setSortingEnabled(__sortingEnabled)
        self.layout = QtWidgets.QGridLayout(self.tab_tableWidget)
        self.layout.setContentsMargins(0, 0, 0, 0)
        self.layout.setObjectName("gridLayout_strategy")
        self.layout.addWidget(self.tableWidget, 0, 0, 1, 4)
        self.layout.addWidget(self.list_instrumentidgroupselect, 0, 4, 1, 3)
        self.layout.addWidget(self.btn_left, 2, 0, 4, 4)
        self.layout.addWidget(self.btn_right, 2, 4, 4, 3)
        self.ReadInstrumentIDGroup()
        for i in range(row_cnt):
            for j in range(4 - 1):
                strs = globalvar.ui.table_instrument.item(i, j + 1).text()
                item = QTableWidgetItem(strs)
                self.tableWidget.setItem(i, j, item)
            item = QTableWidgetItem('选择')
            try:
                if self.dict_EnableInstrumentID[globalvar.ui.table_instrument.item(i, 2).text()]:
                    item.setCheckState(QtCore.Qt.Checked)
                else:
                    item.setCheckState(QtCore.Qt.Unchecked)
            except Exception as e:
                item.setCheckState(QtCore.Qt.Unchecked)
            self.tableWidget.setItem(i, 3, item)
        self.tableWidget.cellChanged.connect(self.OnCellChanged)

        self.setLayout(self.layout)
        # 参数个数
        labelpar = []

        def function_item_clicked(self, QTableWidgetItem):
            check_state = QTableWidgetItem.checkState()
            row = QTableWidgetItem.row()
            if check_state == QtCore.Qt.Checked:
                if row not in self.delete_row:
                    self.delete_row.append(row)
            elif check_state == QtCore.Qt.Unchecked:
                if row in self.delete_row:
                    self.delete_row.remove(row)

        print(self.strategyname)

        try:
            for i in range(len(globalvar.dict_talibcondition[self.strategyname])):
                item = QTableWidgetItem(' 启用该条件')
                if globalvar.dict_talibcondition[self.strategyname][i][1] == 1:
                    item.setCheckState(QtCore.Qt.Checked)
                else:
                    item.setCheckState(QtCore.Qt.Checked)
                self.tableWidget.setItem(i, 0, item)
                item = QTableWidgetItem(globalvar.dict_talibcondition[self.strategyname][i][2])
                self.tableWidget.setItem(i, 1, item)
                item = QTableWidgetItem(globalvar.dict_talibcondition[self.strategyname][i][3])
                self.tableWidget.setItem(i, 2, item)
                item = QTableWidgetItem(globalvar.dict_talibcondition[self.strategyname][i][4])
                self.tableWidget.setItem(i, 3, item)
        except Exception as e:
            print("DialogEditInstrumentID InitUI Error:" + repr(e))

        try:
            parnum = 0
            for i in range(len(module_talib.dict_talibparameter[self.strategyname][3][0])):
                parnum = parnum + 1
                tempparlabel2 = QLabel(self)
                EditPar = QLineEdit(self)
                EditPar2 = QLineEdit(self)
                tempparlabel2.setText(str(module_talib.dict_talibparameter[self.strategyname][3][0][0]))
                tempparlabel2.move(60, 230 + parnum * 40)
                EditPar.setText('>' + str(module_talib.dict_talibparameter[self.strategyname][3][0][1]))
                EditPar.move(200, 230 + parnum * 40)
                EditPar.resize(120, 30)
                EditPar2.setText('趋势条件')
                EditPar2.move(400, 230 + parnum * 40)
                EditPar2.resize(120, 30)
        except Exception as e:
            print("talib.csv格式错误 Error:" + repr(e))
            return

        self.btn_ok = QPushButton('添加指标条件', self)
        self.btn_ok.move(300, 480)
        self.btn_ok.resize(300, 50)
        Edit2 = QLineEdit(self)
        Edit2.setText('（该指标条件可用于组合成策略）')
        Edit2.move(360, 550)
        Edit2.resize(180, 30)

        self.setGeometry(500, 600, 420, 450)
        self.show()
        try:
            global config
            config = configparser.ConfigParser()
            config.read('vnctptd.ini', encoding='utf-8')
            brokeid = config.get('setting', 'brokeid')
            investor = config.get('setting', 'investor')
            password = config.get('setting', 'password')
            appid = config.get('setting', 'appid')
            userproductinfo = config.get('setting', 'userproductinfo')
            authcode = config.get('setting', 'authcode')
            address1 = config.get('setting', 'address1')
            address2 = config.get('setting', 'address2')
            address3 = config.get('setting', 'address3')
            print('read %s %s %s' % (investor, password, appid))
            self.Edit_brokerid.setText(brokeid)
            self.Edit_investor.setText(investor)
            self.Edit_password.setText(password)
            self.Edit_APPID.setText(appid)
            self.Edit_authcode.setText(authcode)
            self.Edit_auserproductinfo.setText(userproductinfo)
            self.Edit_addr1.setText(address1)
            self.Edit_addr2.setText(address2)
            self.Edit_addr3.setText(address3)
        except Exception as e:
            print("initUI Error:" + repr(e))


# 打开量化回测结果窗口
class DialogFinishResult(QtWidgets.QDialog):
    def __init__(self, titlepath, indexfilename):
        super().__init__()
        self.path = titlepath
        self.setWindowIcon(QIcon('ico/ico_doc.ico'))
        self.InitUI(indexfilename)

    def Function_UpdateEquityCurve(self):
        try:
            # 读取资金曲线数据文件，并更新到pyqtgraph
            filename = self.path + self.table_thispargroup.selectedItems()[0].text() + '_' + \
                       self.table_thispargroup.selectedItems()[
                           1].text() + '_' + self.table_thispargroup.selectedItems()[2].text() + '_' + \
                       self.table_thispargroup.selectedItems()[
                           3].text() + '_' + self.table_thispargroup.selectedItems()[4].text() + '_' + \
                       self.table_thispargroup.selectedItems()[5].text() + '.txt'
            data_backtest = []
            # index=0
            with open(filename, 'r') as f:
                for line in f:
                    linelist = line.strip('\n').split(',')
                    data_backtest.append(float(linelist[2]))
        except Exception as e:
            pass

    def Function_UpdateEquityCurveByFileName(self, filename):
        # 读取资金曲线数据文件，并更新到pyqtgraph
        try:
            data_backtest = []
            with open(filename, 'r') as f:
                for line in f:
                    linelist = line.strip('\n').split(',')
                    data_backtest.append(float(linelist[2]))
            self.curve_realtime.setData(np.hstack(data_backtest))
        except Exception as e:
            pass

    def InitUI(self, indexfilename):

        self.setWindowFlags(QtCore.Qt.Dialog | QtCore.Qt.WindowStaysOnBottomHint | QtCore.Qt.WindowCloseButtonHint)
        self.layout = QHBoxLayout()
        self.table_pargroup = QtWidgets.QTableWidget()
        self.table_pargroup.setObjectName("table_pargroup")
        self.table_pargroup.setColumnCount(15)
        self.table_pargroup.setRowCount(0)
        self.table_pargroup.setEditTriggers(QTableView.NoEditTriggers)
        self.table_pargroup.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.table_pargroup.setHorizontalHeaderLabels(
            ['', '操作', '参数1', '参数2', '参数3', '参数4', '参数5', '参数6', '权益', '收益率', '胜率', '盈亏比', '交易次数', '夏普率', '索提诺比率'])
        self.table_pargroup.setRowHeight(0, 28)
        self.table_pargroup.setColumnWidth(0, 40)
        self.table_pargroup.setColumnWidth(1, 40)
        self.table_pargroup.setColumnWidth(2, 40)
        self.table_pargroup.setColumnWidth(3, 40)
        self.table_pargroup.setColumnWidth(4, 40)
        self.table_pargroup.setColumnWidth(5, 40)
        self.table_pargroup.setColumnWidth(6, 40)
        self.table_pargroup.setColumnWidth(7, 90)
        self.table_pargroup.setColumnWidth(8, 85)
        self.table_pargroup.setColumnWidth(9, 85)
        self.table_pargroup.setColumnWidth(10, 85)
        self.table_pargroup.setSelectionMode(QAbstractItemView.SingleSelection)  # 设置只能选中一行
        self.table_pargroup.clicked.connect(self.Function_UpdateEquityCurve)
        self.table_pargroup.doubleClicked.connect(self.Function_UpdateEquityCurve)
        self.table_pargroup.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
        # 资金曲线图
        self.wincurl = pg.GraphicsLayoutWidget(show=True)
        self.wincurl.setWindowTitle('回测资金曲线B')
        self.plt_realtime = self.wincurl.addPlot(title="回测资金曲线B")
        self.curve_realtime = self.plt_realtime.plot(pen='y')
        self.plt_realtime.setMouseEnabled(x=False, y=False)  # 禁用轴操作
        self.wincurl.showMaximized()
        # 资金曲线图
        self.tab_tableWidget = QtWidgets.QWidget()
        self.tab_tableWidget.setObjectName("tab_tableWidget")
        self.list_backtestlog = QtWidgets.QListWidget(self.tab_tableWidget)
        self.list_backtestlog.setObjectName("list_backtestlog")
        _translate = QtCore.QCoreApplication.translate
        __sortingEnabled = self.list_backtestlog.isSortingEnabled()
        self.list_backtestlog.setSortingEnabled(False)
        self.list_backtestlog.setSortingEnabled(__sortingEnabled)
        self.layout = QtWidgets.QGridLayout(self.tab_tableWidget)
        self.layout.setContentsMargins(0, 0, 0, 0)
        self.layout.setObjectName("layout")
        self.layout.addWidget(self.table_pargroup, 0, 0, 200, 50)
        self.layout.addWidget(self.wincurl, 200, 0, 100, 50)
        self.setLayout(self.layout)
        lindid = 0
        with open(indexfilename, 'r') as f:
            for line in f:
                strlist = line.split(",")
                self.table_pargroup.insertRow(lindid)
                item = QTableWidgetItem(strlist[0])
                self.table_pargroup.setItem(lindid, 0, item)
                item = QTableWidgetItem(strlist[1])
                self.table_pargroup.setItem(lindid, 1, item)
                item = QTableWidgetItem(strlist[2])
                self.table_pargroup.setItem(lindid, 2, item)
                item = QTableWidgetItem(strlist[3])
                self.table_pargroup.setItem(lindid, 3, item)
                item = QTableWidgetItem(strlist[4])
                self.table_pargroup.setItem(lindid, 4, item)
                item = QTableWidgetItem(strlist[5])
                self.table_pargroup.setItem(lindid, 5, item)
                item = QTableWidgetItem(strlist[6])
                self.table_pargroup.setItem(lindid, 6, item)
                item = QTableWidgetItem(strlist[7])
                self.table_pargroup.setItem(lindid, 7, item)
                item = QTableWidgetItem(strlist[8])
                self.table_pargroup.setItem(lindid, 8, item)
                item = QTableWidgetItem(strlist[9])
                self.table_pargroup.setItem(lindid, 9, item)
                item = QTableWidgetItem(strlist[10])
                self.table_pargroup.setItem(lindid, 10, item)
                item = QTableWidgetItem(strlist[11])
                self.table_pargroup.setItem(lindid, 11, item)
                lindid += 1


# 打开回测文件K线窗口
class DialogBackTestKline(QtWidgets.QDialog):
    signal_backtestkline = pyqtSignal(list)

    def __init__(self, titlepath):
        super().__init__()
        self.path = titlepath
        self.setWindowIcon(QIcon('ico/kline.ico'))
        self.InitUI()

        if titlepath != '':
            print('LoadData')
            timer = QTimer()  # 初始化一个定时器
            timer.timeout.connect(self.LoadData)
            timer.start(3000)  # 设置计时间隔并启动

    def Function_UpdateEquityCurve(self):
        try:
            # 读取资金曲线数据文件，并更新到pyqtgraph
            filename = self.path + self.table_thispargroup.selectedItems()[0].text() + '_' + \
                       self.table_thispargroup.selectedItems()[
                           1].text() + '_' + self.table_thispargroup.selectedItems()[2].text() + '_' + \
                       self.table_thispargroup.selectedItems()[
                           3].text() + '_' + self.table_thispargroup.selectedItems()[4].text() + '_' + \
                       self.table_thispargroup.selectedItems()[5].text() + '.txt'
            data_backtest = []

            with open(filename, 'r') as f:
                for line in f:
                    linelist = line.strip('\n').split(',')
                    data_backtest.append(float(linelist[2]))
        except Exception as e:
            pass

    def Function_UpdateEquityCurveByFileName(self, filename):
        # 读取资金曲线数据文件，并更新到pyqtgraph
        try:
            data_backtest = []
            with open(filename, 'r') as f:
                for line in f:
                    linelist = line.strip('\n').split(',')
                    data_backtest.append(float(linelist[2]))
            self.curve_realtime.setData(np.hstack(data_backtest))
        except Exception as e:
            pass

    # 从文件读取更新当日K线图
    def UpdateKlineUIFromFile(self, filename):
        try:
            self.dict_dataframe_kline_M1 = pd.DataFrame(
                {'datetime': [], 'recordid': [], 'tradingday': [], 'klinetime': [], 'instrumentid': [], 'open': [],
                 'close': [], 'low': [], 'high': [],
                 'vol': []}, index=[])
            self.data_kline_M1 = [(0, 0, 0, 0, 0, 0, 0), ]
            global kid, count
            kid = 1
            fname = globalvar.currpath + "\\" + filename
            print(fname)
            self.ticklist = []
            firstline = True
            if os.path.isfile(fname):
                for line in open(fname):
                    QApplication.processEvents()

                    if firstline:
                        firstline = False
                    else:
                        ld = line.split(',')
                        dd = datetime.strptime(ld[0], "%Y-%m-%d %H:%M:%S")
                        temp = (kid,
                                float(ld[0][:9].replace('-', '')),
                                float(ld[0][11:].replace(':', '')) / 100000.0,
                                float(ld[1]),
                                float(ld[2]),
                                float(ld[3]),
                                int(float(ld[5])))
                        self.data_kline_M1.append(temp)
                        self.ticklist.append(ld[0])
                        self.dict_dataframe_kline_M1 = self.dict_dataframe_kline_M1.append({
                            'datetime': ld[0],
                            'recordid': '{:0>8s}'.format(str(kid)),
                            'tradingday': (dd.strftime("%Y-%m-%d")).replace('-', ''),
                            'klinetime': float(dd.strftime("%H:%M:%S").replace(':', '')) / 1000000,
                            'instrumentid': ld[8].replace('\n', ''),
                            'open': float(ld[1]),
                            'close': float(ld[4]),
                            'low': float(ld[3]),
                            'high': float(ld[2]),
                            'vol': int(float(ld[5])),
                        }, ignore_index=True)
                        kid = kid + 1
            self.plt_kline.removeItem(self.item)
            self.item = CandlestickItem2(self.data_kline_M1)  # 原始数据,对应（0,0）幅图
            try:
                self.plt_kline.addItem(self.item)
                count += 1
            except Exception as e:
                print("UpdateKlineUIFromFileB Error:" + repr(e))

            # 横坐标刻度
            xax = self.plt_kline.getAxis('bottom')  # 坐标轴x
            xdict = dict(enumerate(self.ticklist))
            xax.setTicks([xdict.items()])
        except Exception as e:
            print("UpdateKlineUIFromFile Error:" + repr(e))

    def Function_UpdateEquityCurve2(self):
        # 回测窗口，双击记录显示资金曲线
        try:
            # 读取资金曲线数据文件，并更新到pyqtgraph
            self.selectbacktestcurl = False
            tempstr = self.table_thispargroup.selectedItems()[
                          1].text() + '_' + self.table_thispargroup.selectedItems()[2].text() + '_' + \
                      self.table_thispargroup.selectedItems()[
                          3].text() + '_' + self.table_thispargroup.selectedItems()[4].text() + '_' + \
                      self.table_thispargroup.selectedItems()[5].text() + '_' + \
                      self.table_thispargroup.selectedItems()[
                          6].text() + '.txt'
            filename_curl = self.table_thispargroup.selectedItems()[0].text() + '/' + tempstr
            filename_tradingrecord = self.table_thispargroup.selectedItems()[0].text() + '/tradingrecord/' + tempstr
            list_tradingday = self.AddTradingRecordShow(filename_tradingrecord)
            data_backtest = []
            data_index_buy = []
            data_value_buy = []
            data_index_sell = []
            data_value_sell = []
            index = 0
            with open(filename_curl, 'r') as f:
                for line in f:
                    linelist = line.strip('\n').split(',')
                    data_backtest.append(float(linelist[2]))
                    index += 1
                    if len(linelist[1]) == 5:
                        linelist[1] = '0' + linelist[1]
                    for key in list_tradingday[0]:
                        if key == linelist[0] + linelist[1]:
                            data_index_buy.append(index)
                            data_value_buy.append(float(linelist[2]))
                    for key in list_tradingday[1]:
                        if key == linelist[0] + linelist[1]:
                            data_index_sell.append(index)
                            data_value_sell.append(float(linelist[2]))

            self.curve_realtime.setData(np.hstack(data_backtest))
            self.curve_buy.setData(np.hstack(data_index_buy),
                                   np.hstack(data_value_buy))
            self.curve_sell.setData(np.hstack(data_index_sell),
                                    np.hstack(data_value_sell))

        except Exception as e:
            pass

    # 由外部更新资金曲线
    def Function_UpdateEquityCurveByFileName2(self, filename, list_tradingday):
        # 读取资金曲线数据文件，并更新到pyqtgraph
        try:
            data_backtest = []
            data_index_buy = []
            data_value_buy = []
            data_index_sell = []
            data_value_sell = []
            index = 0
            with open(filename, 'r') as f:
                for line in f:
                    linelist = line.strip('\n').split(',')
                    data_backtest.append(float(linelist[2]))
                    if len(linelist[1]) == 5:
                        linelist[1] = '0' + linelist[1]
                    index += 1
                    if len(linelist[1]) == 5:
                        linelist[1] = '0' + linelist[1]
                    if 0:
                        for key in list_tradingday[0]:
                            if key == linelist[0] + linelist[1]:
                                data_index_buy.append(index)
                                data_value_buy.append(float(linelist[2]))
                        for key in list_tradingday[1]:
                            if key == linelist[0] + linelist[1]:
                                data_index_sell.append(index)
                                data_value_sell.append(float(linelist[2]))

            self.curve_wincurl.setData(np.hstack(data_backtest))
            self.curve_buy.setData(np.hstack(data_index_buy),
                                   np.hstack(data_value_buy))
            self.curve_sell.setData(np.hstack(data_index_sell),
                                    np.hstack(data_value_sell))
        except Exception as e:
            pass

    # 由外部更新表格
    def UpdateTable(self, arg):
        self.table.insertRow(0)  # 插入一行新行表格
        item = QTableWidgetItem(str(arg[0][2]))
        self.table.setItem(0, 0, item)
        item = QTableWidgetItem(str(arg[0][0][0]))
        self.table.setItem(0, 1, item)
        item = QTableWidgetItem(str(arg[0][0][1]))
        self.table.setItem(0, 2, item)
        item = QTableWidgetItem(str(arg[0][0][2]))
        self.table.setItem(0, 3, item)
        item = QTableWidgetItem(str(arg[0][0][3]))
        self.table.setItem(0, 4, item)
        item = QTableWidgetItem(str(arg[0][0][4]))
        self.table.setItem(0, 5, item)
        item = QTableWidgetItem(str(arg[0][0][5]))
        self.table.setItem(0, 6, item)
        item = QTableWidgetItem(str(arg[0][1][0]))
        self.table.setItem(0, 7, item)
        item = QTableWidgetItem(str(int(arg[0][1][1])) + '%')
        self.table.setItem(0, 8, item)
        item = QTableWidgetItem(str(arg[0][1][2]))
        self.table.setItem(0, 9, item)
        item = QTableWidgetItem(str(arg[0][1][3]))
        self.table.setItem(0, 10, item)
        item = QTableWidgetItem(str(arg[0][1][4]))
        self.table.setItem(0, 11, item)
        item = QTableWidgetItem(str(arg[0][1][5]))
        self.table.setItem(0, 12, item)

    # 更新Title
    def callback_LoadData(self, arg):
        globalvar.ui_bt.setWindowTitle('双击参数组显示该参数组量化回测数据文件K线图【%s】【%s】' % (arg[0], arg[1]))
        self.LoadData()
        self.Function_UpdateEquityCurveByFileName2(self.path, arg[0])

    def InitUI(self):

        self.setWindowFlags(QtCore.Qt.Dialog | QtCore.Qt.WindowStaysOnBottomHint | QtCore.Qt.WindowCloseButtonHint)
        self.layout = QHBoxLayout()
        self.table_section = QtWidgets.QTableWidget()
        self.table_section.setObjectName("table_thispargroup")
        self.table_section.setColumnCount(4)
        self.table_section.setRowCount(0)
        self.table_section.setEditTriggers(QTableView.NoEditTriggers)
        self.table_section.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.table_section.setHorizontalHeaderLabels(['ID', '合约', '开始时间', '结束时间'])
        self.table_section.setRowHeight(0, 28)
        self.table_section.setColumnWidth(0, 100)
        self.table_section.setColumnWidth(1, 100)
        self.table_section.setColumnWidth(2, 100)
        self.table_section.setColumnWidth(3, 100)
        self.table_section.setColumnWidth(4, 100)
        self.table_section.setColumnWidth(5, 100)
        self.table_section.setSelectionMode(QAbstractItemView.SingleSelection)  # 设置只能选中一行
        self.table_section.clicked.connect(self.Function_UpdateEquityCurve)
        self.table_section.doubleClicked.connect(self.Function_UpdateEquityCurve)
        self.table_section.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)

        self.table_record = QtWidgets.QTableWidget()
        self.table_record.setObjectName("table_thispargroup")
        self.table_record.setColumnCount(6)
        self.table_record.setRowCount(0)
        self.table_record.setEditTriggers(QTableView.NoEditTriggers)
        self.table_record.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.table_record.setHorizontalHeaderLabels(['日期', '时间', '合约', '买卖', '开平', '成交价格', '委托手数'])
        self.table_record.setRowHeight(0, 28)
        self.table_record.setColumnWidth(0, 100)
        self.table_record.setColumnWidth(1, 100)
        self.table_record.setColumnWidth(2, 100)
        self.table_record.setColumnWidth(3, 100)
        self.table_record.setColumnWidth(4, 100)
        self.table_record.setColumnWidth(5, 100)
        self.table_record.setSelectionMode(QAbstractItemView.SingleSelection)  # 设置只能选中一行
        self.table_record.clicked.connect(self.Function_UpdateEquityCurve)
        self.table_record.doubleClicked.connect(self.Function_UpdateEquityCurve)
        self.table_record.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)

        # K线图
        self.item = CandlestickItem(data_kline)  # 原始数据,对应（0,0）幅图
        npdata = np.array(data_kline)
        self.wkline = pg.GraphicsWindow(size=(400, 456))
        self.wkline.setWindowTitle('选中时间段数据K线图')
        self.plt_kline = self.wkline.addPlot(1, 1, title="选中时间段数据K线图")
        self.plt_kline.addItem(self.item)
        self.plt_kline.showGrid(True, True)
        self.plt_kline.setMouseEnabled(x=True, y=True)  # 禁用轴操作
        self.wkline.showMaximized()

        # 资金曲线图
        self.wincurl = pg.GraphicsLayoutWidget(show=True)
        self.wincurl.setWindowTitle('选中时间段资金曲线')
        self.plt_wincurl = self.wincurl.addPlot(title="选中时间段资金曲线")
        self.curve_wincurl = self.plt_wincurl.plot(pen='y')
        self.plt_wincurl.setMouseEnabled(x=False, y=False)  # 禁用轴操作
        self.wincurl.showMaximized()

        # 资金曲线图
        self.wincurl1 = pg.GraphicsLayoutWidget(show=True)
        self.wincurl1.setWindowTitle('完整回测资金曲线')
        self.plt_wincurl1 = self.wincurl1.addPlot(title="完整回测资金曲线")
        self.curve_wincurl1 = self.plt_wincurl1.plot(pen='y')
        self.plt_wincurl1.setMouseEnabled(x=False, y=False)  # 禁用轴操作
        self.wincurl1.showMaximized()
        self.layout = QtWidgets.QGridLayout()
        self.layout.setContentsMargins(0, 0, 0, 0)
        self.layout.setObjectName("layout")
        self.layout.addWidget(self.table_section, 0, 0, 300, 20)
        self.layout.addWidget(self.table_record, 0, 20, 300, 30)
        self.layout.addWidget(self.wincurl1, 0, 50, 300, 25)
        self.layout.addWidget(self.wincurl, 300, 0, 100, 75)
        self.layout.addWidget(self.wkline, 400, 0, 60, 75)
        self.setLayout(self.layout)

    def LoadData(self):
        self.UpdateKlineUIFromFile(self.path)


# 参数组分析报告
class DialogParAnalysisReport(QtWidgets.QDialog):
    def __init__(self, indexfilename, csvfile):
        super().__init__()
        self.setWindowIcon(QIcon('ico/ico_doc.ico'))
        self.InitUI(indexfilename)

    def Function_OpenAnalysisReport(self):
        self.webview = WebEngineView()
        self.webview.load(QUrl("https://www.baidu.com"))
        self.setCentralWidget(self.webview)

        with open("reporttemplate/template.html", "r") as f:
            for line in f.readlines():
                line = line.strip('\n')
                strlist = line.split(",")
        pass

    def InitUI(self, indexfilename):

        self.setWindowFlags(QtCore.Qt.Dialog | QtCore.Qt.WindowStaysOnBottomHint | QtCore.Qt.WindowCloseButtonHint)
        self.layout = QHBoxLayout()
        self.table_analysisreport = QtWidgets.QTableWidget()
        self.table_analysisreport.setObjectName("table_analysisreport")
        self.table_analysisreport.setColumnCount(8)
        self.table_analysisreport.setRowCount(0)
        self.table_analysisreport.setEditTriggers(QTableView.NoEditTriggers)
        self.table_analysisreport.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.table_analysisreport.setHorizontalHeaderLabels(
            ['ID', '合约', '盈利参数组个数', '亏损参数组个数', '盈利参数组占比', '盈利参数组平均盈利', '亏损参数组平均亏损', '操作'])
        self.table_analysisreport.setRowHeight(0, 28)
        self.table_analysisreport.setColumnWidth(0, 40)
        self.table_analysisreport.setColumnWidth(1, 40)
        self.table_analysisreport.setColumnWidth(2, 40)
        self.table_analysisreport.setColumnWidth(3, 40)
        self.table_analysisreport.setColumnWidth(4, 40)
        self.table_analysisreport.setColumnWidth(5, 40)
        self.table_analysisreport.setColumnWidth(6, 40)
        self.table_analysisreport.setSelectionMode(QAbstractItemView.NoSelection)  # 设置只能选中一行
        self.table_analysisreport.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
        self.tab_tableWidget = QtWidgets.QWidget()
        self.tab_tableWidget.setObjectName("tab_tableWidget")
        self.list_backtestlog = QtWidgets.QListWidget(self.tab_tableWidget)
        self.list_backtestlog.setObjectName("list_backtestlog")
        _translate = QtCore.QCoreApplication.translate
        __sortingEnabled = self.list_backtestlog.isSortingEnabled()
        self.list_backtestlog.setSortingEnabled(False)
        self.list_backtestlog.setSortingEnabled(__sortingEnabled)
        self.layout = QtWidgets.QGridLayout(self.tab_tableWidget)
        self.layout.setContentsMargins(0, 0, 0, 0)
        self.layout.setObjectName("layout")
        self.layout.addWidget(self.table_analysisreport, 0, 0, 200, 50)
        self.setLayout(self.layout)
        lindid = 0

        totalwin = 0
        totallost = 0
        winnum = 0
        lostnum = 0
        rate = 0
        id = 0
        with open(indexfilename, 'r') as f:
            for line in f:
                strlist = line.split(",")
                if float(strlist[7]) > 1e-7:
                    totalwin = totalwin + float(strlist[7])
                    winnum += 1
                elif float(strlist[7]) < -1e-7:
                    totallost = totallost + float(strlist[7])
                    lostnum += 1

                rate = float(winnum) / float(winnum + lostnum)
                if winnum > 0:
                    winrate = totalwin / winnum
                else:
                    winrate = 0
                if winnum > 0:
                    lostrate = totallost / lostnum
                else:
                    lostrate = 0
            id += 1

        self.table_analysisreport.insertRow(lindid)
        item = QTableWidgetItem('%d' % id)
        self.table_analysisreport.setItem(lindid, 0, item)
        item = QTableWidgetItem('rb')
        self.table_analysisreport.setItem(lindid, 1, item)
        item = QTableWidgetItem('%d' % winnum)
        self.table_analysisreport.setItem(lindid, 2, item)
        item = QTableWidgetItem('%d' % lostnum)
        self.table_analysisreport.setItem(lindid, 3, item)
        item = QTableWidgetItem('%.2f' % rate)
        self.table_analysisreport.setItem(lindid, 4, item)
        item = QTableWidgetItem('%.2f' % winrate)
        self.table_analysisreport.setItem(lindid, 5, item)
        item = QTableWidgetItem('%.2f' % lostrate)
        self.table_analysisreport.setItem(lindid, 6, item)
        Button_report = QPushButton("查看报告")
        Button_report.clicked.connect(self.Function_OpenAnalysisReport)
        self.table_analysisreport.setCellWidget(lindid, 7, Button_report)
